Custom Android Launcher — Why and How do I build one?

Viktor Mukha
Paradox Cat Tech Hub
7 min readNov 7, 2023

Disclaimer. I have presented most of this material at DroidCon 2023 in Berlin. If you prefer a video, you can find it here: https://www.droidcon.com/2023/08/01/custom-launcher-why-and-how-do-i-build-one/

What is a launcher?

According to the source code of Android OS, a Launcher or a Home App is an application which “replaces the home screen and gives access to the contents and features of your device”. It is usually responsible for listing and starting other applications and for hosting widgets.

Here is an example of a launcher:

Guess what your phone screen would look like without a launcher? You would only see what is called System UI:

No launcher in system (only System UI is visible)

A home app is essential for any Android system. Try to start your applications without it!

Every Android device comes with a pre-installed launcher. Device manufacturers may create their own home app, or simply reuse the vanilla launcher that comes with AOSP (Android Open Source Project). Since it is Open Source, you can actually inspect the original launcher source code. For instance, Launcher 3 for Android phones can be found here: https://cs.android.com/android/platform/superproject/main/+/main:packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

User can choose default home app: Settings — Apps — Default Apps — Home app:

Default home app chooser

A default launcher will be the default “HOME” action, which can be triggered by a hardware button or a swipe-up-from-bottom gesture. The selected default home application will always be at the bottom of the activity back stack. In simple words, if you keep going “BACK”, you will always arrive at the default launcher.

Why create new launcher?

There are multiple possible reasons:

  • Performance
  • Features
  • Usability
  • Design
  • Customization

These are the reasons behind every custom launcher you see in the Google Play Store. In fact, most of today’s stock launchers features today were once only available in custom launchers.

If you check Wikipedia, you will find a table with more than 60 launchers for phones/tablets only. Obviously, not all of them can keep up with Android development and some became obsolete when their features were integrated into stock launchers.

Another reason to create a new home app is the plethora of Android devices out there: phones, foldables, tablets, TVs, cars, wearables. They all need a launcher.

Source: https://www.android.com/everyone/

There are many possible applications for Android OS. Here are just a few of them.

  • Vending machines, coffee machines, beer machines
  • Public transport: entertainment, info screens, ticket machines
  • Shared & private transportation: cars, bikes, scooters
  • Smart home, IoT devices

Of course, not all of them run Android (yet), but if they do, they all need a launcher.

How to develop a launcher?

First of all, make your application a launcher. Add this category to your intent filter in AndroidManifest.xml:

<category android:name="android.intent.category.HOME" />

Actual meaning of this category and other related ones can be found in Intents.java, here are the example definitions extracted from this file:

android.intent.category.HOME
This is the home activity, that is the first activity that is displayed when the device boots.

android.intent.category.HOME_MAIN (hidden API, only for platform)
This is the home activity that is displayed when the device is finished setting up and ready for use.

android.intent.category.SECONDARY_HOME
The home activity shown on secondary displays that support showing home activities.

android.intent.category.SETUP_WIZARD (hidden API, only for platform)
This is the setup wizard activity, that is the first activity that is displayed when the user sets up the device for the first time.

android.intent.category.LAUNCHER_APP (hidden API, only for platform)
This is the home activity, that is the activity that serves as the launcher app from there the user can start other apps. Often components with lower/higher priority intent filters handle the home intent, for example SetupWizard, to setup the device and we need to be able to distinguish the home app from these setup helpers.

Next step in becoming a launcher is to list the apps. To get a list of apps, use Package Manager’s queryIntentActivities() API:

val intent = Intent(Intent.ACTION_MAIN)
intent.addCategory(Intent.CATEGORY_LAUNCHER)
val flags = PackageManager.ResolveInfoFlags.of(
PackageManager.MATCH_ALL.toLong())
val activities: List<ResolveInfo> =
context.packageManager.queryIntentActivities(intent, flags)

For ease of use, map this list to your app objects:

data class App(
val name: String,
val packageName: String,
val icon: Drawable?
)

val installedApps = activities.map { resolveInfo ->
App(
name = resolveInfo.loadLabel(packageManager).toString(),
packageName = resolveInfo.activityInfo.packageName,
icon = resolveInfo.loadIcon(packageManager)
)
}

Start an app via such object:

fun App.launch(context: Context) {
val intent = context.packageManager.getLaunchIntentForPackage(packageName) ?: return
context.startActivity(intent)
}

How to display applications?

Let us start by looking at the existing user interface modalities. It seems that the world has settled on multi-screen navigation with a configurable grid of icons grouped with the app names.

However, grid is not the only option. Experiment with simple flat lists, embedded search or filtering using text or speech, fast scrolling using first letters, etc.

Take a look at Niagara Launcher’s approach:

Or it could be as simple as OLauncher:

Also, remember to give users a way to see all of their installed apps in one place. For example using an App Drawer which one could “draw” from the bottom of the screen with a swipe-up gesture:

That said, do not limit yourself to application icons and app widgets only. Get creative and build the user interface around what your users actually need. For example, a SpaceX rocket launcher (pun intended) might look something like this:

Source: https://www.figma.com/community/file/855715967691534013

App Widgets

A story about launchers would be incomplete without talking about App Widgets.

This is an example of a standard clock widget:

I will not bother you with details on implementation or widget types, you can find great official documentation here. If you use Jetpack Compose, check out the Glance library, it is truly great!

Instead, let us discuss the uses and limitations of App Widgets.

It is clear that widgets are quite useful for applications like calendar, clock, and weather. However, if you want to have something like a fully interactive map on your home screen all the time, App Widgets unfortunately are not going to cut it.

And why is that?

  • Interaction. Gestures are limited to only touch and vertical swipe, so as not to conflict with Home App gestures.
  • UI. Not all UI elements are available, so you cannot create a full-featured home screen app as an App Widget.
  • Battery. By default, App Widgets refresh once every 30 minutes (!). That says a lot about the design decisions.

But wait a minute, isn’t that what the default launcher of Android Automotive OS does? Showing a giant interactive map in a launcher?

Yes, it does:

CarLauncher in AAOS based on Android 12

If it is not an App Widget, what is it?

In the source code, Google calls these widgets “Cards”. Cards are implemented in terms of lower-level window management facilities. This facility used to be an ActivityView, which was deprecated and eventually removed in Android 12. Now it is a TaskView, which is rightfully a hidden platform API.

What does “hidden platform API” mean for application developers? Simply put:

  • it should not be used by non-system applications,
  • it will likely change in future Android version.

Yes, there are ways to expose this API to applications, but if you want your application to survive Android updates, I urge you to consider a better design alternative.

Implement the element you want to “embed” directly in the launcher. As long as you have control over the providing app, you can extract the relevant code parts into common libraries and design proper communication between the “Widget” and the “App” yourself.

That said, your launcher should probably still support embedding App Widgets as well, some users depend on it.

We have covered a lot of ground in this story. To summarize, we have learned the following.

  • Launcher is a home screen application.
  • The world needs new launchers that are fast and stable.
  • Now you know how to make an application a launcher, how to list other applications.
  • You should support App Widgets, but do not let them limit your design.

Be creative and focus on what your users need.

--

--

Viktor Mukha
Paradox Cat Tech Hub

Principal Software Architect @ PARADOX CAT GmbH. Android OS expert. Music enthusiast.