Build A Custom Launcher on Android
Introduction
In its most basic form, a launcher is an application that does the following:- it represents the home screen of a device
- it lists and launches applications that are installed on the device
In this tutorial, we are going to create a simple launcher with a basic user interface. It will have two screens:
- a home screen showing the device's wallpaper
- a screen showing the icons and details of the applications installed on the device
1. Requirements
You need to have the following installed and configured on your development machine:- Android SDK and platform tools
- Eclipse IDE 3.7.2 or higher with the ADT plugin
- an emulator or Android device running Android 2.2 or higher
2. Project Setup
Launch Eclipse and create a new Android application project. I'm naming the application SimpleLauncher, but you can name it anything you want. Make sure you use a unique package. The lowest SDK version our launcher supports is Froyo and the target SDK is Jelly Bean.Since we don't want to create an
Activity
, deselect Create Activity. Click Finish to continue.3. Project Manifest
The next step is modifying the AndroidManifest.xml file by adding two activities. The firstActivity
displays the home screen. Let's name it HomeActivity
as shown below.01 02 03 04 05 06 07 08 09 10 11 12 13 | < activity android:name = "ah.hathi.simplelauncher.HomeActivity" android:label = "Simple Launcher Home" android:theme = "@android:style/Theme.Wallpaper.NoTitleBar.Fullscreen" android:launchMode = "singleTask" android:stateNotNeeded = "true" > < intent-filter > < action android:name = "android.intent.action.MAIN" /> < category android:name = "android.intent.category.HOME" /> < category android:name = "android.intent.category.DEFAULT" /> </ intent-filter > </ activity > |
android.intent.category.HOME
and android.intent.category.DEFAULT
to the intent-filter
group, the associated Activity
behaves like a launcher and shows up as an option when you press the device's home button.We also need to set the
launchMode
to singleTask
to make sure that only one instance of this Activity
is held by the system at any time. To show the user's wallpaper, set the theme to Theme.Wallpaper.NoTitleBar.FullScreen
.The second
Activity
we need to add displays the applications that are installed on the user's device. It's also responsible for launching applications. We don't need any special configuration for this Activity
. Name it AppsListActivity
.1 2 3 4 5 | < activity android:name = "ah.hathi.simplelauncher.AppsListActivity" android:theme = "@android:style/Theme.NoTitleBar.Fullscreen" > </ activity > |
4. Activity Layouts
Create an XML file for theHomeActivity
class in the project's res/layout folder and name it activity_home.xml. The layout has a single Button
that responds to click events. Clicking the button takes the user from the home screen to the list of applications.01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 | android:layout_width = "match_parent" android:layout_height = "match_parent" tools:context = ".HomeActivity" > < Button android:id = "@+id/apps_button" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_alignParentRight = "true" android:layout_alignParentTop = "true" android:layout_marginRight = "10dp" android:layout_marginTop = "10dp" android:text = "Show Apps" android:onClick = "showApps" /> </ RelativeLayout > |
AppsListActivity
class in the project's res/layout folder and name it activity_apps_list.xml. The layout contains a ListView
that takes up the entire screen.01 02 03 04 05 06 07 08 09 10 11 12 13 14 | <? xml version = "1.0" encoding = "utf-8" ?> android:layout_width = "match_parent" android:layout_height = "match_parent" android:orientation = "vertical" > < ListView android:id = "@+id/apps_list" android:layout_width = "match_parent" android:layout_height = "match_parent" > </ ListView > </ LinearLayout > |
ListView
. Each list view item represents an application installed on the user's device. It shows the application's icon, label, and package name. We display the application icon using an ImageView
instance and TextView
instances for the label and package name.01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <? xml version = "1.0" encoding = "utf-8" ?> android:layout_width = "match_parent" android:layout_height = "match_parent" android:padding = "10dp" > < ImageView android:id = "@+id/item_app_icon" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_alignParentLeft = "true" android:layout_centerVertical = "true" /> < TextView android:id = "@+id/item_app_label" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_toRightOf = "@+id/item_app_icon" android:paddingLeft = "10dp" /> < TextView android:id = "@+id/item_app_name" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_below = "@+id/item_app_label" android:layout_toRightOf = "@+id/item_app_icon" android:paddingLeft = "10dp" /> </ RelativeLayout > |
5. Implementing the Activity Classes
HomeActivity
With the layouts of the application created, it's time to create the two Activity
classes. When creating the two classes, make sure the name of each class matches the one you specified in the project's manifest file earlier.Create a new class named
HomeActivity
and set android.app.Activity
as its superclass.01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 | package ah.hathi.simplelauncher; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; public class HomeActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_home); } public void showApps(View v){ Intent i = new Intent( this , AppsListActivity. class ); startActivity(i); } } |
onCreate
method, we invoke setContentView
, passing in the layout we created earlier. You may remember that we added a button to the activity_home layout that triggers a method named showApps
. We now need to implement that method in the HomeActivity
class. The implementation is pretty simple, we create an Intent
for the AppsListActivity
class and start it.AppsListActivity
Create another Activity
class named AppsListActivity
and set android.app.Activity
as its superclass. In the class's onCreate
method, we invoke setContentView
, passing in the activity_apps_list layout we created earlier.01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 | package ah.hathi.simplelauncher; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; public class AppsListActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_apps_list); } } |
If you choose Simple Launcher Home, you should see your new home screen with a single button in the top right corner of the screen. You should also see your device's current wallpaper.
Go back to Eclipse and create a class named
AppDetail
that will contain the details of an application, its package name, label, and application icon. The interface is pretty basic as you can see below.1 2 3 4 5 6 7 8 9 | package ah.hathi.simplelauncher; import android.graphics.drawable.Drawable; public class AppDetail { CharSequence label; CharSequence name; Drawable icon; } |
6. Fetching Applications
In theloadApps
method of the AppsListActivity
class, we use the queryIntentActivities
method of the PackageManager
class to fetch all the Intents that have a category of Intent.CATEGORY_LAUNCHER
. The query returns a list of the applications that can be launched by a launcher. We loop through the results of the query and add each item to a list named apps
. Take a look at the following code snippet for clarification.01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 | private PackageManager manager; private List<AppDetail> apps; private void loadApps(){ manager = getPackageManager(); apps = new ArrayList<AppDetail>(); Intent i = new Intent(Intent.ACTION_MAIN, null ); i.addCategory(Intent.CATEGORY_LAUNCHER); List<ResolveInfo> availableActivities = manager.queryIntentActivities(i, 0 ); for (ResolveInfo ri:availableActivities){ AppDetail app = new AppDetail(); app.label = ri.loadLabel(manager); app.name = ri.activityInfo.packageName; app.icon = ri.activityInfo.loadIcon(manager); apps.add(app); } } |
7. Displaying the List of Applications
With theapps
variable containing all the details we need, we can show the list of applications using the ListView
class. We create a simple ArrayAdapter
and override its getView
method to render the list's items. We then associate the ListView
with the adapter.01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | private ListView list; private void loadListView(){ list = (ListView)findViewById(R.id.apps_list); ArrayAdapter<AppDetail> adapter = new ArrayAdapter<AppDetail>( this , R.layout.list_item, apps) { @Override public View getView( int position, View convertView, ViewGroup parent) { if (convertView == null ){ convertView = getLayoutInflater().inflate(R.layout.list_item, null ); } ImageView appIcon = (ImageView)convertView.findViewById(R.id.item_app_icon); appIcon.setImageDrawable(apps.get(position).icon); TextView appLabel = (TextView)convertView.findViewById(R.id.item_app_label); appLabel.setText(apps.get(position).label); TextView appName = (TextView)convertView.findViewById(R.id.item_app_name); appName.setText(apps.get(position).name); return convertView; } }; list.setAdapter(adapter); } |
8. Listening for Clicks
When the user clicks an item in theListView
, the corresponding application should be launched by our launcher. We use the getLaunchIntentForPackage
method of the PackageManager
class to create an Intent
with which we start the application. Take a look at the following code snippet.01 02 03 04 05 06 07 08 09 10 | private void addClickListener(){ list.setOnItemClickListener( new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> av, View v, int pos, long id) { Intent i = manager.getLaunchIntentForPackage(apps.get(pos).name.toString()); AppsListActivity. this .startActivity(i); } }); } |
9. Putting It All Together
To make everything work together, we need to invokeloadApps
, loadListView
, and addClickListener
in the onCreate
method of the AppsListActivity
class as shown below.1 2 3 4 5 6 7 8 | protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_apps_list); loadApps(); loadListView(); addClickListener(); } |
Comments
Post a Comment