How to set default app launcher programmatically?
Asked Answered
H

5

49

I am creating a launcher (kiosk) app that will be downloadable through google. When first installing this application the user has the ability of choosing which launcher (mine or the stock) will be the default. I am trying to bring this up manually if the user does not make my application the default launcher. I want the user to be forced into selecting ALWAYS instead of JUST ONCE when that dialog comes up, otherwise the dialog will continue to appear periodically with a friendly message. This is what I have attempted so far.

I created a method to check for if my application is the default

/**
 * method checks to see if app is currently set as default launcher
 * @return boolean true means currently set as default, otherwise false
 */ 
private boolean isMyAppLauncherDefault() {
    final IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
    filter.addCategory(Intent.CATEGORY_HOME);

    List<IntentFilter> filters = new ArrayList<IntentFilter>();
    filters.add(filter);

    final String myPackageName = getPackageName();
    List<ComponentName> activities = new ArrayList<ComponentName>();
    final PackageManager packageManager = (PackageManager) getPackageManager();

    packageManager.getPreferredActivities(filters, activities, null);

    for (ComponentName activity : activities) {
        if (myPackageName.equals(activity.getPackageName())) {
            return true;
        }
    }
    return false;
}   

Then I make the attempt of launching the chooser

/**
 * method starts an intent that will bring up a prompt for the user
 * to select their default launcher. It comes up each time it is
 * detected that our app is not the default launcher
 */
private void launchAppChooser() {
    Log.d(TAG, "launchAppChooser()");
    Intent intent = new Intent(Intent.ACTION_MAIN);
    intent.addCategory(Intent.CATEGORY_HOME);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);
}

When I do this I am not receiving the choice between my app and the stock launcher. I tried using startActivity(Intent.createChooser(intent, "Please set launcher settings to ALWAYS")); and I get the choices between my app and the stock launcher, however, I don't get the options ALWAYS or JUST ONCE.

I can create a custom dialog for this instead of launching chooser but I need to know how to set the default app launcher programmatically. Thanks in advance!

Highhat answered 16/1, 2015 at 19:46 Comment(3)
You shouldn't force the user to do something. Let them decide what they want. What if the user wants to try your app but then wants to switch back immediately. The built in chooser will do just fine.Sadness
Actually this is the common behavior of launcher apps. Download any launcher application built for children and it is this way. The reason is actually protecting the user (children). The purpose of this is to further ensure that the child is in a contained and controlled environment. That is why most launcher apps built for kids, e.g. Famigo and others, have this behavior.Highhat
can our app be chosen without promting to the user, is there a method to give package name for default launcher?Depository
M
87

This is actually possible with a little workaround:

Create an empty Activity that acts as a launcher called FakeLauncherActivity. Add it to your manifest as a disabled component:

<activity
    android:name="com.path.to.your.FakeLauncherActivity"
    android:enabled="false">
    <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>

Check whether your desired launcher activity is the default one (with the isMyAppLauncherDefault() from your question).

If not, offer the user to choose the preferred launcher activity like this:

public static void resetPreferredLauncherAndOpenChooser(Context context) {
    PackageManager packageManager = context.getPackageManager();
    ComponentName componentName = new ComponentName(context, com.path.to.your.FakeLauncherActivity.class);
    packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);

    Intent selector = new Intent(Intent.ACTION_MAIN);
    selector.addCategory(Intent.CATEGORY_HOME);
    selector.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(selector);

    packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, PackageManager.DONT_KILL_APP);
}

This method temporarily enables FakeLauncherActivity, which leads to a change in the set of available launcher activities, which forces Android to forget its default launcher. You will see something like...

521-735/system_process I/PackageManager﹕ Result set changed, dropping preferred activity for Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 } type null

... in your log.

The method then simply opens a launcher intent where you can see all installed launchers and the buttons "Always" / "Just once". Finally, the method disables FakeLauncherActivity again so that it doesn't display in the list.

You could repeat that as often as you want and only let the user proceed if your desired launcher activity is set as default.

Microphysics answered 3/6, 2015 at 10:17 Comment(13)
Wow! After all this time a viable answer! Thank you good sir!!Highhat
What version of Android have you used this code in? I cannot get it to work in 4.4.2Daye
The methods and constants in the code are supported by all Android API levels. I also tested it on an Android 4.4.2 device. At which point does it fail for you?Microphysics
Sorry for the late reply, I have just tried again with no luck. The dialog does appear the first time, but if the user selects another launcher as default, then reopens this app, the dialog never seems to appear again.Daye
Alright, that's why you'd have to check if your launcher is the default one (isMyAppLauncherDefault()) every time the user opens or returns to your app.Microphysics
I figured out that my answer is just a copy of this: https://mcmap.net/q/356333/-clearing-and-setting-the-default-home-application ... so please go ahead and upvote that one please. When I answered here, I didn't know where I've got my solution from, but now I found the source again.Microphysics
Could you please provide some more information about what exactly does not work? I successfully tested it on stock Android 6.0.Microphysics
yes, it works for provided intent, however I want to reset default browser. So my intent is created for action_view, some https link used as data. And for this 'browser'-intent this code works only below android 6.Dagon
@Daye Hi. I know this question is a year ago, but now I have the same problem testing the above code on Andorid 4.4.2. Have you solved it yet?Thank you in advance!Grossularite
I also cannot get the default app. Could you look at the issue at #40502210Omniumgatherum
can our app be chosen without promting to the user, is there a method to give package name for default launcher?Depository
is it possible to prioritise order of the app in select dialog?Depository
i'm developing launcher app but i'm facing challenging in preserving the default launcher as my launcher app i.e. i set my launcher as default, after reboot my device, device again ask me for set default launcher. Please guide me so that i can fix this issue in my project. Thanks in advance.Christmastide
Y
9

The isMyAppLauncherDefault() function in the question doesn't always work for some reason. This code might be better for determining what is the default package for the HOME screen.

Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
ResolveInfo resolveInfo = getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
String currentHomePackage = resolveInfo.activityInfo.packageName;
Yarber answered 23/8, 2016 at 14:18 Comment(0)
C
7

I want the user to be forced into selecting ALWAYS instead of JUST ONCE when that dialog comes up

That is not possible, except perhaps on rooted devices, barring some security flaw in Android.

When I do this I am not receiving the choice between my app and the stock launcher

Correct. If a default has already been chosen, this will simply launch the default.

I tried using startActivity(Intent.createChooser(intent, "Please set launcher settings to ALWAYS")); and I get the choices between my app and the stock launcher, however, I don't get the options ALWAYS or JUST ONCE.

Correct. createChooser() forces a choice, but does not allow setting a default.

Cruiserweight answered 16/1, 2015 at 20:34 Comment(3)
What you have described is what I have been experiencing, but this is not what I have noticed from other apps. If you download Famigo app from google play store, you will see what I mean. When Famigo is not default app, a dialog comes up saying that user must set the app as default otherwise certain features cannot be accessed. You have to choose ALWAYS. Once you do that, when you go to device settings it says as default launcher that "chosen to launch app by default for some actions". Inside the Famigo app, you can undo this default setting with one button click.Highhat
@portfoliobuilder: Then sometime I will work on figuring out how they do it, then report the security flaw to Google and try to get the flaw fixed.Cruiserweight
Hi I have rooted device. How can forcefully show my launcher as default launcher[Without any popup's even user press on Home button] How to forcefully press on ALWAYS through programaticallyGesticulative
L
4

If you are implementing Google EMM solution (Dedicated Device):

https://developer.android.com/work/dpc/dedicated-devices/cookbook

// Create an intent filter to specify the Home category.
IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
filter.addCategory(Intent.CATEGORY_HOME);
filter.addCategory(Intent.CATEGORY_DEFAULT);

// Set the activity as the preferred option for the device.
ComponentName activity = new ComponentName(context, KioskModeActivity.class);
DevicePolicyManager dpm =
    (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
dpm.addPersistentPreferredActivity(adminName, filter, activity);
Lustig answered 25/9, 2019 at 7:53 Comment(3)
how to get an adminName ?Christmastide
@PriteshVishwakarma here is the documentation: developer.android.com/guide/topics/admin/device-adminLustig
And if you want to set another app to be the launcher, construct the ComponentName with strings : new ComponentName("com.example.myotherapp", "com.example.myotherapp.MainActivity") .Infralapsarian
M
4

Android Q (API 29) has RoleManager. Let's say your app is a Launcher.

[AndroidManifest.xml]
<activity
    ... />

    <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>


private val startForResult = registerForActivityResult(
    ActivityResultContracts.StartActivityForResult()
) { activityResult ->
    if (activityResult.resultCode == Activity.RESULT_OK) {
        // Perhaps log the result here.
    }
}

private fun showLauncherSelection() {
    val roleManager = requireActivity().getSystemService(Context.ROLE_SERVICE)
            as RoleManager
    if (roleManager.isRoleAvailable(RoleManager.ROLE_HOME) &&
        !roleManager.isRoleHeld(RoleManager.ROLE_HOME)
    ) {
        val intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_HOME)
        startForResult.launch(intent)
    }
}

When you call showLauncherSelection(), you should see a dialog similar to the following.

enter image description here

There are other roles, such as ROLE_BROWSER, ROLE_DIALER, ROLE_SMS, and such.

Marchelle answered 20/1, 2022 at 22:9 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.