How can I listen to which app has been chosen as Launcher Application?

Viewed 875

I tried to implement a functionality that allows user to pick default Android's default Launcher Application. Also, I need to receive information which application has been chosen. But there is a problem with that approach.

To let user pick Launcher Application, we can simply start given intent:

val selector = Intent(Intent.ACTION_MAIN)
selector.addCategory(Intent.CATEGORY_HOME)
selector.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(selector)

It results in such dialog:

enter image description here

What I observed, if I use startActivity, the Launcher Application is set nicely and works as intended, but if I use startActivityForResult, then I will get some callback, but the Launcher Application will not be set at all. Also, there was nothing interesting in intent received in onActivityResult.

Then, I tried using IntentSender instead.

The code looks as follows:

val selector = Intent(Intent.ACTION_MAIN)
selector.addCategory(Intent.CATEGORY_HOME)
selector.flags = Intent.FLAG_ACTIVITY_NEW_TASK
val receiver = Intent(this, MyBroadcastReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(this, 0, receiver, PendingIntent.FLAG_UPDATE_CURRENT)
val chooser = Intent.createChooser(selector, "Select a Home app", pendingIntent.intentSender);
startActivity(chooser)

The receiver looks as follows:

class MyBroadcastReceiver: BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        val componentName = intent.extras.getParcelable<ComponentName>(Intent.EXTRA_CHOSEN_COMPONENT)
        //com.example.myapp if my app was choosen
        val pkg = componentName.packageName
    }
}

This results in default chooser, without options "JUST ONCE" or "ALWAYS". I don't have exact picture, but it looks similar to this one:

enter image description here

This works in a way, in the receiver's onReceive method I get ComponenName object, that holds selected app packageName. The problem is - again - Launcher Application is not set!

So question is: How can I let user set Launcher Application, and also receive information which one has he chosen?

2 Answers

Try using the following code:

PackageManager localPackageManager = getPackageManager();
Intent intent = new Intent("android.intent.action.MAIN");
intent.addCategory("android.intent.category.HOME");
String launcherName = localPackageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY).activityInfo.packageName;
Log.e("Current launcher Package Name:",launcherName);

With getPreferredActivities() you can retrieve all activities which are preferred by the user. This should include the launcher as well.

Then you could try to implement a getPreferredLauncher() function to get the current Launcher. But since there's no way to listen for this change, you'd have to query it proactively within a Service or whenever you'd assume the data could have changed:

fun PackageManager.getPreferredLauncher(): ComponentName? {
    val filters = mutableListOf<IntentFilter>()
    val components = mutableListOf<ComponentName>()
    getPreferredActivities(filters, components, null)
    filters.forEachIndexed { (i, it) ->
        if (it.hasAction(ACTION_MAIN) && it.hasCategory(CATEGORY_LAUNCHER))
            return@getPreferredLauncher components[i]
    }
    return null
}

Please consider this code a draft only, as I didn't have any setup to actually run it.

Related