Search code examples
javaandroidandroid-intentlauncherhomescreen

choosing home launcher app using intents


I am writing an Android app which contains an activity that should act as the home launcher activity when enabled. To do this, I enable the activity before calling startActivityForResult with CATEGORY_HOME as an intent category to enable choosing of the activity as the home launcher activity. The activity is then disabled after being selected to enable home-key launching only when enabled.

My problem is when the prompt asking the user to choose the launcher activity appears and the user selects the default home activity instead of the custom launcher activity, subsequent chooser intents fail and only result in the home screen being shown.

Here is the code for starting the launcher activity chooser:

PackageManager pm = getActivity().getPackageManager();
                            pm.setComponentEnabledSetting(new ComponentName(getActivity(), CustomLauncherActivity.class),
                                    PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
Intent i = new Intent(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_HOME);
startActivityForResult(i, REQUEST_CODE_ENABLE_HOME_LAUNCHER);

When the launcher chooser is shown and the user selects the device's default launcher activity instead of the custom launcher, my app is minimized and the home screen is shown. Re-entering the app and repeating the chooser process then results in the launcher chooser not being shown again, but the home screen displayed instead.

Is there a solution for this? How is it possible to recover from the user selecting the incorrect home-launcher activity?


Solution

  • I found a solution to the problem. I replaced the code above with the following:

    PackageManager pm = getActivity().getPackageManager();
    pm.setComponentEnabledSetting(new     ComponentName(getActivity(), CustomLauncherActivity.class), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
    
    writeSetupFlag(true);
    Intent i = new Intent(Intent.ACTION_MAIN);
    i.addCategory(Intent.CATEGORY_HOME);
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    i.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
    startActivity(i);
    

    Note the flags added to the intent (FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_SINGLE_TOP) and the changing of startActivityForResult to simply 'startActivity'.

    writeSetupFlag writes a flag to SharedPreferences indicating that the chooser was shown:

    private void writeSetupFlag(boolean bInSetup) {
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext());
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putBoolean(getString(R.string.setup_flag_active), bInSetup);
        editor.commit();
    }
    

    This enables us to determine if the chooser has been shown before. So suppose the user selected the wrong home activity during the choosing process (i.e. not our activity), the home screen will be shown. Re-launching the app will trigger reading of the flag written and we can detect that the chooser was shown, but the user selected the wrong launcher.

    So we can first check whether our activity was set as the home launcher:

    Intent intent = new Intent(Intent.ACTION_MAIN);
    intent.addCategory(Intent.CATEGORY_HOME);
    PackageManager pm = context.getPackageManager();
    pm.setComponentEnabledSetting(new ComponentName(context, CustomLauncherActivity.class),
                    PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
    ResolveInfo resolveInfo = pm.resolveActivity(intent, PackageManager.MATCH_ALL);
    pm.setComponentEnabledSetting(new ComponentName(context, CustomLauncherActivity.class),
    PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
    String currentHomePackage = resolveInfo.activityInfo.packageName;
    String customlauncherpackage = context.getApplicationContext().getPackageName();
    

    Now if our activity is not the home launcher, we check the setup flag:

    if (!currentHomePackage.equals(customlauncherpackage)) {
        boolean bChooserShown;
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext());
        bChooserShown = sharedPreferences.getBoolean(getString(R.string.setup_flag_active), false);
    
        if (bChooserShown) {
            //Display a dialog to the user indicating that they selected the wrong launcher before and will have to reset the launcher from settings.
            ... dialog here ...
            //Then redirect to settings
            if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
                Intent i = new Intent(Settings.ACTION_HOME_SETTINGS, null);
                startActivityForResult(i, REQUEST_LAUNCH_HOME_SETTINGS);
            } else {
                Intent i = new Intent(Settings.ACTION_SETTINGS, null);
                startActivityForResult(i, REQUEST_LAUNCH_HOME_SETTINGS);
            }
       }
       else {
           //do chooser process
       }
    

    So by using the flag in SharedPreferences we can recover from the user selecting the incorrect home launcher application when we display a chooser.