Repository: arnabc/simplelauncher Branch: master Commit: 4396af4f2730 Files: 29 Total size: 42.9 KB Directory structure: gitextract_dpr258s4/ ├── .gitignore ├── README.md ├── SimpleLauncher/ │ ├── build.gradle │ ├── libs/ │ │ └── android-support-v4.jar │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── java/ │ │ └── ch/ │ │ └── arnab/ │ │ └── simplelauncher/ │ │ ├── AppListAdapter.java │ │ ├── AppListFragment.java │ │ ├── AppModel.java │ │ ├── AppsGridFragment.java │ │ ├── AppsLoader.java │ │ ├── GridFragment.java │ │ ├── HomeScreen.java │ │ └── PackageIntentReceiver.java │ └── res/ │ ├── layout/ │ │ ├── homescreen.xml │ │ └── list_item_icon_text.xml │ ├── menu/ │ │ └── home_screen.xml │ ├── values/ │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ ├── values-sw600dp/ │ │ └── dimens.xml │ ├── values-sw720dp-land/ │ │ └── dimens.xml │ ├── values-v11/ │ │ └── styles.xml │ └── values-v14/ │ └── styles.xml ├── build.gradle ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # built application files *.apk *.ap_ # files for the dex VM *.dex # Java class files *.class # generated files bin/ gen/ # Local configuration file (sdk path, etc) local.properties # Eclipse project files .classpath .project # Android Studio .idea/ .gradle build/ /*/local.properties /*/out /*/*/build /*/*/production *.iml *.iws *.ipr *~ *.swp ================================================ FILE: README.md ================================================ Simple Launcher ============== An example custom launcher for Android, read more here: http://arnab.ch/blog/2013/08/how-to-write-custom-launcher-app-in-android/ ------- MIT License. Copyright 2016 Arnab Chakraborty. https://arnab.ch ================================================ FILE: SimpleLauncher/build.gradle ================================================ buildscript { repositories { jcenter(); } dependencies { classpath 'com.android.tools.build:gradle:4.0.0' } } apply plugin: 'com.android.application' repositories { jcenter(); } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' } android { compileSdkVersion 28 defaultConfig { minSdkVersion 19 targetSdkVersion 29 } } ================================================ FILE: SimpleLauncher/src/main/AndroidManifest.xml ================================================ ================================================ FILE: SimpleLauncher/src/main/java/ch/arnab/simplelauncher/AppListAdapter.java ================================================ package ch.arnab.simplelauncher; import android.annotation.TargetApi; import android.content.Context; import android.os.Build; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.TextView; import java.util.ArrayList; import java.util.Collection; /** * Created by Arnab Chakraborty */ public class AppListAdapter extends ArrayAdapter { private final LayoutInflater mInflater; public AppListAdapter (Context context) { super(context, android.R.layout.simple_list_item_2); mInflater = LayoutInflater.from(context); } public void setData(ArrayList data) { clear(); if (data != null) { addAll(data); } } @Override @TargetApi(Build.VERSION_CODES.HONEYCOMB) public void addAll(Collection items) { //If the platform supports it, use addAll, otherwise add in loop if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { super.addAll(items); }else{ for(AppModel item: items){ super.add(item); } } } /** * Populate new items in the list. */ @Override public View getView(int position, View convertView, ViewGroup parent) { View view; if (convertView == null) { view = mInflater.inflate(R.layout.list_item_icon_text, parent, false); } else { view = convertView; } AppModel item = getItem(position); ((ImageView)view.findViewById(R.id.icon)).setImageDrawable(item.getIcon()); ((TextView)view.findViewById(R.id.text)).setText(item.getLabel()); return view; } } ================================================ FILE: SimpleLauncher/src/main/java/ch/arnab/simplelauncher/AppListFragment.java ================================================ package ch.arnab.simplelauncher; import android.os.Bundle; import android.support.v4.app.ListFragment; import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; import java.util.ArrayList; /** * Created by Arnab Chakraborty */ public class AppListFragment extends ListFragment implements LoaderManager.LoaderCallbacks> { AppListAdapter mAdapter; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); setEmptyText("No Applications"); mAdapter = new AppListAdapter(getActivity()); setListAdapter(mAdapter); // till the data is loaded display a spinner setListShown(false); // create the loader to load the apps list in background getLoaderManager().initLoader(0, null, this); } @Override public Loader> onCreateLoader(int id, Bundle bundle) { return new AppsLoader(getActivity()); } @Override public void onLoadFinished(Loader> loader, ArrayList apps) { mAdapter.setData(apps); if (isResumed()) { setListShown(true); } else { setListShownNoAnimation(true); } } @Override public void onLoaderReset(Loader> loader) { mAdapter.setData(null); } } ================================================ FILE: SimpleLauncher/src/main/java/ch/arnab/simplelauncher/AppModel.java ================================================ package ch.arnab.simplelauncher; import android.content.Context; import android.content.pm.ApplicationInfo; import android.graphics.drawable.Drawable; import java.io.File; /** * @credit http://developer.android.com/reference/android/content/AsyncTaskLoader.html */ public class AppModel { private final Context mContext; private final ApplicationInfo mInfo; private String mAppLabel; private Drawable mIcon; private boolean mMounted; private final File mApkFile; public AppModel(Context context, ApplicationInfo info) { mContext = context; mInfo = info; mApkFile = new File(info.sourceDir); } public ApplicationInfo getAppInfo() { return mInfo; } public String getApplicationPackageName() { return getAppInfo().packageName; } public String getLabel() { return mAppLabel; } public Drawable getIcon() { if (mIcon == null) { if (mApkFile.exists()) { mIcon = mInfo.loadIcon(mContext.getPackageManager()); return mIcon; } else { mMounted = false; } } else if (!mMounted) { // If the app wasn't mounted but is now mounted, reload // its icon. if (mApkFile.exists()) { mMounted = true; mIcon = mInfo.loadIcon(mContext.getPackageManager()); return mIcon; } } else { return mIcon; } return mContext.getResources().getDrawable(android.R.drawable.sym_def_app_icon); } void loadLabel(Context context) { if (mAppLabel == null || !mMounted) { if (!mApkFile.exists()) { mMounted = false; mAppLabel = mInfo.packageName; } else { mMounted = true; CharSequence label = mInfo.loadLabel(context.getPackageManager()); mAppLabel = label != null ? label.toString() : mInfo.packageName; } } } } ================================================ FILE: SimpleLauncher/src/main/java/ch/arnab/simplelauncher/AppsGridFragment.java ================================================ package ch.arnab.simplelauncher; import android.content.Intent; import android.os.Bundle; import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; import android.view.View; import android.widget.GridView; import java.util.ArrayList; /** * Created by Arnab Chakraborty */ public class AppsGridFragment extends GridFragment implements LoaderManager.LoaderCallbacks> { AppListAdapter mAdapter; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); setEmptyText("No Applications"); mAdapter = new AppListAdapter(getActivity()); setGridAdapter(mAdapter); // till the data is loaded display a spinner setGridShown(false); // create the loader to load the apps list in background getLoaderManager().initLoader(0, null, this); } @Override public Loader> onCreateLoader(int id, Bundle bundle) { return new AppsLoader(getActivity()); } @Override public void onLoadFinished(Loader> loader, ArrayList apps) { mAdapter.setData(apps); if (isResumed()) { setGridShown(true); } else { setGridShownNoAnimation(true); } } @Override public void onLoaderReset(Loader> loader) { mAdapter.setData(null); } @Override public void onGridItemClick(GridView g, View v, int position, long id) { AppModel app = (AppModel) getGridAdapter().getItem(position); if (app != null) { Intent intent = getActivity().getPackageManager().getLaunchIntentForPackage(app.getApplicationPackageName()); if (intent != null) { startActivity(intent); } } } } ================================================ FILE: SimpleLauncher/src/main/java/ch/arnab/simplelauncher/AppsLoader.java ================================================ package ch.arnab.simplelauncher; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.support.v4.content.AsyncTaskLoader; import java.text.Collator; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Comparator; /** * @credit http://developer.android.com/reference/android/content/AsyncTaskLoader.html */ public class AppsLoader extends AsyncTaskLoader> { ArrayList mInstalledApps; final PackageManager mPm; PackageIntentReceiver mPackageObserver; public AppsLoader(Context context) { super(context); mPm = context.getPackageManager(); } @Override public ArrayList loadInBackground() { // retrieve the list of installed applications List apps = mPm.getInstalledApplications(0); if (apps == null) { apps = new ArrayList(); } final Context context = getContext(); // create corresponding apps and load their labels ArrayList items = new ArrayList(apps.size()); for (int i = 0; i < apps.size(); i++) { String pkg = apps.get(i).packageName; // only apps which are launchable if (context.getPackageManager().getLaunchIntentForPackage(pkg) != null) { AppModel app = new AppModel(context, apps.get(i)); app.loadLabel(context); items.add(app); } } // sort the list Collections.sort(items, ALPHA_COMPARATOR); return items; } @Override public void deliverResult(ArrayList apps) { if (isReset()) { // An async query came in while the loader is stopped. We // don't need the result. if (apps != null) { onReleaseResources(apps); } } ArrayList oldApps = apps; mInstalledApps = apps; if (isStarted()) { // If the Loader is currently started, we can immediately // deliver its results. super.deliverResult(apps); } // At this point we can release the resources associated with // 'oldApps' if needed; now that the new result is delivered we // know that it is no longer in use. if (oldApps != null) { onReleaseResources(oldApps); } } @Override protected void onStartLoading() { if (mInstalledApps != null) { // If we currently have a result available, deliver it // immediately. deliverResult(mInstalledApps); } // watch for changes in app install and uninstall operation if (mPackageObserver == null) { mPackageObserver = new PackageIntentReceiver(this); } if (takeContentChanged() || mInstalledApps == null ) { // If the data has changed since the last time it was loaded // or is not currently available, start a load. forceLoad(); } } @Override protected void onStopLoading() { // Attempt to cancel the current load task if possible. cancelLoad(); } @Override public void onCanceled(ArrayList apps) { super.onCanceled(apps); // At this point we can release the resources associated with 'apps' // if needed. onReleaseResources(apps); } @Override protected void onReset() { // Ensure the loader is stopped onStopLoading(); // At this point we can release the resources associated with 'apps' // if needed. if (mInstalledApps != null) { onReleaseResources(mInstalledApps); mInstalledApps = null; } // Stop monitoring for changes. if (mPackageObserver != null) { getContext().unregisterReceiver(mPackageObserver); mPackageObserver = null; } } /** * Helper method to do the cleanup work if needed, for example if we're * using Cursor, then we should be closing it here * * @param apps */ protected void onReleaseResources(ArrayList apps) { // do nothing } /** * Perform alphabetical comparison of application entry objects. */ public static final Comparator ALPHA_COMPARATOR = new Comparator() { private final Collator sCollator = Collator.getInstance(); @Override public int compare(AppModel object1, AppModel object2) { return sCollator.compare(object1.getLabel(), object2.getLabel()); } }; } ================================================ FILE: SimpleLauncher/src/main/java/ch/arnab/simplelauncher/GridFragment.java ================================================ package ch.arnab.simplelauncher; /* * Created by Thomas Barrasso on 9/11/12. * Copyright (c) 2012 Loupe Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import android.content.Context; import android.content.res.Resources; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.support.v4.app.Fragment; import android.util.TypedValue; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.animation.AnimationUtils; import android.widget.AdapterView; import android.widget.FrameLayout; import android.widget.GridView; import android.widget.LinearLayout; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; /** * Based on {@link android.app.ListFragment} but adapted for {@link GridView}. */ public class GridFragment extends Fragment { static final int INTERNAL_EMPTY_ID = 0x00ff0001; static final int INTERNAL_PROGRESS_CONTAINER_ID = 0x00ff0002; static final int INTERNAL_LIST_CONTAINER_ID = 0x00ff0003; final private Handler mHandler = new Handler(); final private Runnable mRequestFocus = new Runnable() { public void run() { mGrid.focusableViewAvailable(mGrid); } }; final private AdapterView.OnItemClickListener mOnClickListener = new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView parent, View v, int position, long id) { onGridItemClick((GridView) parent, v, position, id); } }; ListAdapter mAdapter; GridView mGrid; View mEmptyView; TextView mStandardEmptyView; View mProgressContainer; View mGridContainer; CharSequence mEmptyText; boolean mGridShown; public GridFragment() { } /** * Provide default implementation to return a simple grid view. Subclasses * can override to replace with their own layout. If doing so, the * returned view hierarchy must have a GridView whose id * is {@link android.R.id#list android.R.id.list} and can optionally * have a sibling view id {@link android.R.id#empty android.R.id.empty} * that is to be shown when the grid is empty. * *

If you are overriding this method with your own custom content, * consider including the standard layout {@link android.R.layout#list_content} * in your layout file, so that you continue to retain all of the standard * behavior of ListFragment. In particular, this is currently the only * way to have the built-in indeterminant progress state be shown. */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final Context context = getActivity(); FrameLayout root = new FrameLayout(context); // ------------------------------------------------------------------ LinearLayout pframe = new LinearLayout(context); pframe.setId(INTERNAL_PROGRESS_CONTAINER_ID); pframe.setOrientation(LinearLayout.VERTICAL); pframe.setVisibility(View.GONE); pframe.setGravity(Gravity.CENTER); ProgressBar progress = new ProgressBar(context, null, android.R.attr.progressBarStyleLarge); pframe.addView(progress, new FrameLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); root.addView(pframe, new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); // ------------------------------------------------------------------ FrameLayout lframe = new FrameLayout(context); lframe.setId(INTERNAL_LIST_CONTAINER_ID); TextView tv = new TextView(getActivity()); tv.setId(INTERNAL_EMPTY_ID); tv.setGravity(Gravity.CENTER); lframe.addView(tv, new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); GridView lv = new GridView(getActivity()); lv.setId(android.R.id.list); lv.setDrawSelectorOnTop(false); lv.setColumnWidth(convertDpToPixels(60, getActivity())); lv.setStretchMode(GridView.STRETCH_COLUMN_WIDTH); lv.setNumColumns(GridView.AUTO_FIT); lv.setHorizontalSpacing(convertDpToPixels(20, getActivity())); lv.setVerticalSpacing(convertDpToPixels(20, getActivity())); lv.setSmoothScrollbarEnabled(true); // disable overscroll if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { lv.setOverScrollMode(ListView.OVER_SCROLL_NEVER); } lframe.addView(lv, new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); root.addView(lframe, new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); // ------------------------------------------------------------------ root.setLayoutParams(new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); return root; } /** * Attach to grid view once the view hierarchy has been created. */ @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); ensureGrid(); } /** * Detach from {@link GridView} */ @Override public void onDestroyView() { mHandler.removeCallbacks(mRequestFocus); mGrid = null; mGridShown = false; mEmptyView = mProgressContainer = mGridContainer = null; mStandardEmptyView = null; super.onDestroyView(); } public static int convertDpToPixels(float dp, Context context){ Resources resources = context.getResources(); return (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, dp, resources.getDisplayMetrics() ); } /** * This method will be called when an item in the grid is selected. * Subclasses should override. Subclasses can call * getGridView().getItemAtPosition(position) if they need to access the * data associated with the selected item. * * @param g The {@link GridView} where the click happened * @param v The view that was clicked within the {@link GridView} * @param position The position of the view in the grid * @param id The row id of the item that was clicked */ public void onGridItemClick(GridView g, View v, int position, long id) { } /** * Provide the cursor for the {@link GridView}. */ public void setGridAdapter(ListAdapter adapter) { final boolean hadAdapter = (mAdapter != null); mAdapter = adapter; if (mGrid != null) { mGrid.setAdapter(adapter); if (!mGridShown && !hadAdapter) { // The grid was hidden, and previously didn't have an // adapter. It is now time to show it. setGridShown(true, (getView().getWindowToken() != null)); } } } /** * Set the currently selected grid item to the specified * position with the adapter's data * * @param position */ public void setSelection(int position) { ensureGrid(); mGrid.setSelection(position); } /** * Get the position of the currently selected grid item. */ public int getSelectedItemPosition() { ensureGrid(); return mGrid.getSelectedItemPosition(); } /** * Get the cursor row ID of the currently selected grid item. */ public long getSelectedItemId() { ensureGrid(); return mGrid.getSelectedItemId(); } /** * Get the activity's {@link GridView} widget. */ public GridView getGridView() { ensureGrid(); return mGrid; } /** * The default content for a ListFragment has a TextView that can * be shown when the grid is empty. If you would like to have it * shown, call this method to supply the text it should use. */ public void setEmptyText(CharSequence text) { ensureGrid(); if (mStandardEmptyView == null) { throw new IllegalStateException("Can't be used with a custom content view"); } mStandardEmptyView.setText(text); if (mEmptyText == null) { mGrid.setEmptyView(mStandardEmptyView); } mEmptyText = text; } /** * Control whether the grid is being displayed. You can make it not * displayed if you are waiting for the initial data to show in it. During * this time an indeterminant progress indicator will be shown instead. * *

Applications do not normally need to use this themselves. The default * behavior of ListFragment is to start with the grid not being shown, only * showing it once an adapter is given with {@link #setGridAdapter(ListAdapter)}. * If the grid at that point had not been shown, when it does get shown * it will be do without the user ever seeing the hidden state. * * @param shown If true, the grid view is shown; if false, the progress * indicator. The initial value is true. */ public void setGridShown(boolean shown) { setGridShown(shown, true); } /** * Like {@link #setGridShown(boolean)}, but no animation is used when * transitioning from the previous state. */ public void setGridShownNoAnimation(boolean shown) { setGridShown(shown, false); } /** * Control whether the grid is being displayed. You can make it not * displayed if you are waiting for the initial data to show in it. During * this time an indeterminant progress indicator will be shown instead. * * @param shown If true, the grid view is shown; if false, the progress * indicator. The initial value is true. * @param animate If true, an animation will be used to transition to the * new state. */ private void setGridShown(boolean shown, boolean animate) { ensureGrid(); if (mProgressContainer == null) { throw new IllegalStateException("Can't be used with a custom content view"); } if (mGridShown == shown) { return; } mGridShown = shown; if (shown) { if (animate) { mProgressContainer.startAnimation(AnimationUtils.loadAnimation( getActivity(), android.R.anim.fade_out)); mGridContainer.startAnimation(AnimationUtils.loadAnimation( getActivity(), android.R.anim.fade_in)); } else { mProgressContainer.clearAnimation(); mGridContainer.clearAnimation(); } mProgressContainer.setVisibility(View.GONE); mGridContainer.setVisibility(View.VISIBLE); } else { if (animate) { mProgressContainer.startAnimation(AnimationUtils.loadAnimation( getActivity(), android.R.anim.fade_in)); mGridContainer.startAnimation(AnimationUtils.loadAnimation( getActivity(), android.R.anim.fade_out)); } else { mProgressContainer.clearAnimation(); mGridContainer.clearAnimation(); } mProgressContainer.setVisibility(View.VISIBLE); mGridContainer.setVisibility(View.GONE); } } /** * Get the ListAdapter associated with this activity's {@link GridView}. */ public ListAdapter getGridAdapter() { return mAdapter; } private void ensureGrid() { if (mGrid != null) { return; } View root = getView(); if (root == null) { throw new IllegalStateException("Content view not yet created"); } if (root instanceof GridView) { mGrid = (GridView) root; } else { mStandardEmptyView = (TextView)root.findViewById(INTERNAL_EMPTY_ID); if (mStandardEmptyView == null) { mEmptyView = root.findViewById(android.R.id.empty); } else { mStandardEmptyView.setVisibility(View.GONE); } mProgressContainer = root.findViewById(INTERNAL_PROGRESS_CONTAINER_ID); mGridContainer = root.findViewById(INTERNAL_LIST_CONTAINER_ID); View rawGridView = root.findViewById(android.R.id.list); if (!(rawGridView instanceof GridView)) { if (rawGridView == null) { throw new RuntimeException( "Your content must have a GridView whose id attribute is " + "'android.R.id.list'"); } throw new RuntimeException( "Content has view with id attribute 'android.R.id.list' " + "that is not a GridView class"); } mGrid = (GridView) rawGridView; if (mEmptyView != null) { mGrid.setEmptyView(mEmptyView); } else if (mEmptyText != null) { mStandardEmptyView.setText(mEmptyText); mGrid.setEmptyView(mStandardEmptyView); } } mGridShown = true; mGrid.setOnItemClickListener(mOnClickListener); if (mAdapter != null) { ListAdapter adapter = mAdapter; mAdapter = null; setGridAdapter(adapter); } else { // We are starting without an adapter, so assume we won't // have our data right away and start with the progress indicator. if (mProgressContainer != null) { setGridShown(false, false); } } mHandler.post(mRequestFocus); } } ================================================ FILE: SimpleLauncher/src/main/java/ch/arnab/simplelauncher/HomeScreen.java ================================================ package ch.arnab.simplelauncher; import android.os.Bundle; import android.app.Activity; import android.support.v4.app.FragmentActivity; import android.view.Menu; public class HomeScreen extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.homescreen); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.home_screen, menu); return true; } } ================================================ FILE: SimpleLauncher/src/main/java/ch/arnab/simplelauncher/PackageIntentReceiver.java ================================================ package ch.arnab.simplelauncher; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; /** * Helper class to look for interesting changes to the installed apps * so that the loader can be updated. * * @Credit http://developer.android.com/reference/android/content/AsyncTaskLoader.html */ public class PackageIntentReceiver extends BroadcastReceiver { final AppsLoader mLoader; public PackageIntentReceiver(AppsLoader loader) { mLoader = loader; IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addAction(Intent.ACTION_PACKAGE_CHANGED); filter.addDataScheme("package"); mLoader.getContext().registerReceiver(this, filter); // Register for events related to sdcard installation. IntentFilter sdFilter = new IntentFilter(); sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); mLoader.getContext().registerReceiver(this, sdFilter); } @Override public void onReceive(Context context, Intent intent) { // Tell the loader about the change. mLoader.onContentChanged(); } } ================================================ FILE: SimpleLauncher/src/main/res/layout/homescreen.xml ================================================ ================================================ FILE: SimpleLauncher/src/main/res/layout/list_item_icon_text.xml ================================================ ================================================ FILE: SimpleLauncher/src/main/res/menu/home_screen.xml ================================================

================================================ FILE: SimpleLauncher/src/main/res/values/dimens.xml ================================================ 16dp 16dp ================================================ FILE: SimpleLauncher/src/main/res/values/strings.xml ================================================ SimpleLauncher Settings Hello world! ================================================ FILE: SimpleLauncher/src/main/res/values/styles.xml ================================================ ================================================ FILE: SimpleLauncher/src/main/res/values-sw600dp/dimens.xml ================================================ ================================================ FILE: SimpleLauncher/src/main/res/values-sw720dp-land/dimens.xml ================================================ 128dp ================================================ FILE: SimpleLauncher/src/main/res/values-v11/styles.xml ================================================ ================================================ FILE: SimpleLauncher/src/main/res/values-v14/styles.xml ================================================ ================================================ FILE: build.gradle ================================================ // Top-level build file where you can add configuration options common to all sub-projects/modules. ================================================ FILE: gradle/wrapper/gradle-wrapper.properties ================================================ #Sun Mar 16 17:01:50 GMT+05:30 2014 distributionBase = GRADLE_USER_HOME distributionPath = wrapper/dists zipStoreBase = GRADLE_USER_HOME zipStorePath = wrapper/dists distributionUrl = https\://services.gradle.org/distributions/gradle-6.1.1-all.zip ================================================ FILE: gradlew ================================================ #!/usr/bin/env bash ############################################################################## ## ## Gradle start up script for UN*X ## ############################################################################## # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS="" APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" warn ( ) { echo "$*" } die ( ) { echo echo "$*" echo exit 1 } # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false case "`uname`" in CYGWIN* ) cygwin=true ;; Darwin* ) darwin=true ;; MINGW* ) msys=true ;; esac # For Cygwin, ensure paths are in UNIX format before anything is touched. if $cygwin ; then [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` fi # Attempt to set APP_HOME # Resolve links: $0 may be a link PRG="$0" # Need this for relative symlinks. while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG=`dirname "$PRG"`"/$link" fi done SAVED="`pwd`" cd "`dirname \"$PRG\"`/" >&- APP_HOME="`pwd -P`" cd "$SAVED" >&- CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" else JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD="java" which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD if [ $? -ne 0 ] ; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" fi fi # For Darwin, add options to specify how the application appears in the dock if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi # For Cygwin, switch paths to Windows format before running java if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` SEP="" for dir in $ROOTDIRSRAW ; do ROOTDIRS="$ROOTDIRS$SEP$dir" SEP="|" done OURCYGPATTERN="(^($ROOTDIRS))" # Add a user-defined pattern to the cygpath arguments if [ "$GRADLE_CYGPATTERN" != "" ] ; then OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" fi # Now convert the arguments - kludge to limit ourselves to /bin/sh i=0 for arg in "$@" ; do CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` else eval `echo args$i`="\"$arg\"" fi i=$((i+1)) done case $i in (0) set -- ;; (1) set -- "$args0" ;; (2) set -- "$args0" "$args1" ;; (3) set -- "$args0" "$args1" "$args2" ;; (4) set -- "$args0" "$args1" "$args2" "$args3" ;; (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules function splitJvmOpts() { JVM_OPTS=("$@") } eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" ================================================ FILE: gradlew.bat ================================================ @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS= set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if "%ERRORLEVEL%" == "0" goto init echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto init echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :init @rem Get command-line arguments, handling Windowz variants if not "%OS%" == "Windows_NT" goto win9xME_args if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. set CMD_LINE_ARGS= set _SKIP=2 :win9xME_args_slurp if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* goto execute :4NT_args @rem Get arguments from the 4NT Shell from JP Software set CMD_LINE_ARGS=%$ :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% :end @rem End local scope for the variables with windows NT shell if "%ERRORLEVEL%"=="0" goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 exit /b 1 :mainEnd if "%OS%"=="Windows_NT" endlocal :omega ================================================ FILE: settings.gradle ================================================ include ':SimpleLauncher'