Affiliate links on Android Authority may earn us a commission. Learn more.
How to build a custom launcher in Android Studio - Part One
When it comes to Android customization, the launcher is the holy grail. This is where it’s at. It’s the trump card Android has always had over iOS. It’s what makes Android the most customizable operating system on pretty much any platform.
Read Next: The best Android app makers for creating apps and building them with zero code
When it comes to Android customization, the launcher is the holy grail.
How might you go about creating your own Android launcher? Read this post — and the upcoming part two — that’s how!
The game plan
Creating an Android launcher is obviously a rather in-depth project with a lot of factors. It is almost always running, so it needs to be as perfectly bug-free as possible.
No pressure!
It would be too large an undertaking to do a completely start-to-finish tutorial here. Instead, I’m going to go over all the crucial features you need to turn any app into a launcher and I’ll leave it to you to put them all together and add your own personal spin. (part two will include the full source for a very basic skeleton of a launcher!)
A launcher is almost constantly running, meaning that it needs to be as perfectly bug-free as humanly possible!
You’ll need some background knowledge before taking on this project. To that end, I recommend this post on creating your first app from Gary Sims.
What does an app need in order to become a launcher?
- It needs to be mapped to the home button and launch when your device starts up.
- It needs to display custom wallpapers.
- It needs to show and launch apps from the homescreen and from an app drawer.
- It needs multiple screens through which you can scroll.
- It needs widgets.
There’s more, but if you can get these basics down then you’ll be well on your way. Let’s dive in and get creating out homescreen launcher!
Create a new project with an empty activity and then follow these steps.
The Android manifest
The first item on our agenda is to make our app into a launcher. That means making sure the Android system identifies it as such, loads it up when the system first boots, and shows it whenever you hit the “home” button.
This is simple — you just need to add the following two lines to your Android manifest file inside the activity tag:
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
Now you’ll have the option to select this application as your launcher. Which technically means it is a launcher.
That was easy!
Right now, it doesn’t look like much of a launcher, and so the next thing to do is add a custom wallpaper. This is also pretty simple. You just have to add the following code to your styles.xml file in the resources folder.
<item name="android:windowShowWallpaper">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
Just a couple of lines added and we’ve got something that looks and behaves like a launcher. I’d say that’s a good start!
How to launch apps
Launching apps is a simple matter of using intents. Intents allow us to launch activities, apps, functions, and more. In this case, we’re going to launch Google Chrome using its package name, which is com.android.chrome.
To do that, you simply need this code:
Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.android.chrome");
startActivity(launchIntent);
Remember to import the Intent class (select it and press alt + return when it’s underlined). We could add a button instead of the TextView in our layout XML and set it to launch Chrome. We could also use this as a cool way to easily set any app as our default “home.” Place this in the onCreate method or onResume and any time you press home, you’ll launch Chrome or the app of your choosing!
But that’s probably not what most would want to do. So instead, let’s do the button thing. We’ll use an ImageView and give it the ID chromeButton. Choose any image for now. I picked a star.
Now add an onClick:
public void onChromeButtonClick(View v) {
Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.android.chrome");
startActivity(launchIntent);
}
Wouldn’t it be nicer if we could use the correct icon? Surprise! we can.
To do this you’ll need to reverse-engineer a handy method to grab the icon from any app and return it as a drawable:
public static Drawable getActivityIcon(Context context, String packageName, String activityName) {
PackageManager pm = context.getPackageManager();
Intent intent = new Intent();
intent.setComponent(new ComponentName(packageName, activityName));
ResolveInfo resolveInfo = pm.resolveActivity(intent, 0);
return resolveInfo.loadIcon(pm);
}
After that, we can simply set the icon as we like it in onCreate():
ImageView chromeIcon = (ImageView) findViewById(R.id.chromeButton);
chromeIcon.setImageDrawable(this, getActivityIcon("com.android.chrome", "com.google.android.apps.chrome.Main"));
When using this method, you need both the package name and the activity name. I’m using an app called Package Names Viewer to get these. We’ll get to how to do this dynamically in a moment.
I’ve used a public static method so it’s accessible from other classes without creating multiple instances of our MainActivity. This method will likely prove to be a useful one.
You’ve already built enough of an app here to do something useful. You could very easily create a launcher simply showing your favorite apps in a line, for example. Most people will want to be a little more ambitious.
How to create an app drawer
Now that we can show and launch one app, we should be able to show and launch all apps. We just need to get a list of all the package names on the device, cycle through it, and load the icons into a recycler view.
Create a new activity in your project and call the java and xml files AppsDrawer.java and apps_drawer.xml respectively. Make sure you have some way for the user to launch this second activity too. I added a small menu button at the bottom of the screen.
In here, we’re going to display a list (recycler view) that will simply show all our icons and allow our user to select them in order to launch the app of their choice. Add a recycler view to apps_drawer.xml and give it the ID appsList.
Adding a recycler view is a whole other thing, so I won’t get into that now. Instead, check out this tutorial on recycler views and use the same names for my resource files and views as I did there. There is a method to this madness after all!
Create a separate XML file for the layout of the items in your row, and a new adapter class to populate the recycler view. You also need to create one more class, called appInfo and will have the simplest interface imaginable:
public class AppInfo {
CharSequence label;
CharSequence packageName;
Drawable icon;
}
As you might have guessed, we’ll just be using this to store information about the apps in our list.
Now create your adapter class and add the following code:
public class RAdapter extends RecyclerView.Adapter<RAdapter.ViewHolder> {
private List<AppInfo> appsList;
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView textView;
public ImageView img;
//This is the subclass ViewHolder which simply
//'holds the views' for us to show on each row
public ViewHolder(View itemView) {
super(itemView);
//Finds the views from our row.xml
textView = (TextView) itemView.findViewById(R.id.text);
img = (ImageView) itemView.findViewById(R.id.img);
itemView.setOnClickListener(this);
}
@Override
public void onClick (View v) {
int pos = getAdapterPosition();
Context context = v.getContext();
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(appsList.get(pos).packageName.toString());
context.startActivity(launchIntent);
Toast.makeText(v.getContext(), appsList.get(pos).label.toString(), Toast.LENGTH_LONG).show();
}
}
public RAdapter(Context c) {
//This is where we build our list of app details, using the app
//object we created to store the label, package name and icon
PackageManager pm = c.getPackageManager();
appsList = new ArrayList<AppInfo>();
Intent i = new Intent(Intent.ACTION_MAIN, null);
i.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> allApps = pm.queryIntentActivities(i, 0);
for(ResolveInfo ri:allApps) {
AppInfo app = new AppInfo();
app.label = ri.loadLabel(pm);
app.packageName = ri.activityInfo.packageName;
app.icon = ri.activityInfo.loadIcon(pm);
appsList.add(app);
}
}
@Override
public void onBindViewHolder(RAdapter.ViewHolder viewHolder, int i) {
//Here we use the information in the list we created to define the views
String appLabel = appsList.get(i).label.toString();
String appPackage = appsList.get(i).packageName.toString();
Drawable appIcon = appsList.get(i).icon;
TextView textView = viewHolder.textView;
textView.setText(appLabel);
ImageView imageView = viewHolder.img;
imageView.setImageDrawable(appIcon);
}
@Override
public int getItemCount() {
//This method needs to be overridden so that Androids knows how many items
//will be making it into the list
return appsList.size();
}
@Override
public RAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//This is what adds the code we've written in here to our target view
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.row, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
}
Remember to import all classes as necessary. Check the comments for a bit more information on what everything does. I highly recommend reading through that Recycler View post if you’re not already familiar.
This is the main unique bit:
PackageManager pm = c.getPackageManager();
appsList = new ArrayList<AppInfo>();
Intent i = new Intent(Intent.ACTION_MAIN, null);
i.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> allApps = pm.queryIntentActivities(i, 0);
for(ResolveInfo ri:allApps) {
AppInfo app = new AppInfo();
app.label = ri.loadLabel(pm);
app.packageName = ri.activityInfo.packageName;
app.icon = ri.activityInfo.loadIcon(pm);
appsList.add(app);
}
This simply loops through our runnable installed apps and grabs the necessary details, icons, and more from there.
Of course, row.xml includes an image view (img) and a text view (textView) which become our icon and our app label.
Meanwhile, the onClickListener added to the view holder allows us to run the app when clicked — just like a real launcher!
The next steps
At this point the end is in sight and you’re getting close to having a fully functional launcher! But there is still a bit left to do.
In part two, we’ll be populating our recycler view in an separate thread to keep things snappy. After that, we’ll add multiple homescreens to swipe through using fragments and take a quick look at how to host widgets.
Stay tuned for part two and be sure to post your questions down below!
Update: How to build a custom launcher in Android Studio – Part Two