Search code examples
androidandroid-intentprovisioning

DevicePolicyManager.enableSystemApp() method does not work as expected


I'm trying to use enableSystemApp method to activate default system apps after provisioning device with the app that is set to device owner mode.

There are two methods to do this:

1) void enableSystemApp (ComponentName admin, String packageName) - in this case you need to pass package name explicitly as String. It works fine, the app gets enabled.

For example, calling this

devicePolicyManager.enableSystemApp(deviceAdminComponent, "com.google.android.gm");

enables default Gmail client, which is disabled after provisioning.

2) int enableSystemApp (ComponentName admin, Intent intent) - in this case, you need to pass an implicit intent and Android should enable all system apps that match this intent. In addition, this method returns int number of apps that match the intent. And here's the problem - I can't get this method to work, it always returns 0 and doesn't enable anything.

Here's the snippet I'm trying to use:

Intent intent = new Intent();
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_APP_EMAIL);
int i = devicePolicyManager.enableSystemApp(deviceAdminComponent, intent);

It does not work and i == 0 in this case. What am I doing wrong?

Any help is appreciated!


Solution

  • Under the hood, the method that accepts an intent queries to get the list of activities that respond to that intent and then loops through the list passing in the package name string to enable the package. It's similar to doing this:

    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_MAIN);
    intent.addCategory(Intent.CATEGORY_APP_EMAIL);
    List<ResolveInfo> infoes = getPackageManager()
        .queryIntentActivities(intent, MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE);
    for (ResolveInfo info in infoes) {
      devicePolicyManager.enableSystemApp(deviceAdminComponent, info.activityInfo.packageName);
    }
    

    Since you are able to enable the app using the package name string, the fault most likely lies in the way the intent is being resolved - which is supported by the fact that it always returns 0.

    It is counter-intuitive, but my suspicion is that the application does not resolve the ACTION_MAIN intent because the app is disabled. Have you tried a less generic intent? I would try the following

    Intent i;
    
    // #1
    // This goes full circle, but I expect it should work
    i = getPackageManager().getLaunchIntentForPackage("com.google.an‌​droid.gm")
    
    // #2
    i = new Intent(Intent.ACTION_SEND).setPackageName("com.google.android.gm");
    
    // #3
    // Generic, but should resolve _all_ email apps - not just the default one. 
    // The mailto schema filters out non-email apps
    i = new Intent(Intent.ACTION_VIEW , Uri.parse("mailto:"));
    

    Option #1 and #2 are more academic. Both require the package name at which point you may as well use the string overload of enableSystemApp. Option #3 is my best guess for something generic that might still work, but it's possible that it still won't work because the app is disabled.

    Note: I find it interesting that enableSystemApp only passes the MATCH_DIRECT_BOOT_AWARE and MATCH_DIRECT_BOOT_UNAWARE flags when querying activities that can resolve the intent, because the MATCH_DISABLED_COMPONENTS and MATCH_SYSTEM_ONLY flags seem much more relevant in this situation.