Background
Android apps can gain some special rights using admin policies, like turning the lock screen on.
As such, those apps cannot be uninstalled till the user has revoked their admin rights.
I wish to have a function that will check if a given app (given a package name of the app) has admin rights, and if so, i will open the admin settings page of this app, to allow the user to revoke its rights.
The problem
As it turns out, there is already a function that does it.
First you get an instance of the DevicePolicyManager :
DevicePolicyManager dpm=(DevicePolicyManager)context.getSystemService(Context.DEVICE_POLICY_SERVICE);
Then you are supposed to call isAdminActive , and get a result of true/false.
However, this function's parameter is ComponentName, meaning it needs not only the package name, but also the path to a specific class of the app.
An alternative would be to query all active admin apps, using getActiveAdmins.
Later, I you can go to the admin page using:
final Intent intent=new Intent();
intent.setComponent(new ComponentName("com.android.settings","com.android.settings.DeviceAdminSettings"));
startActivity(intent);
or even more specifically, to enable/disable the app admin rights :
final Intent intent=new Intent();
intent.setComponent(new ComponentName("com.android.settings","com.android.settings.DeviceAdminAdd"));
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,componentName);
activity.startActivity(intent);
However, both of those ways seems a bit hacky, as they do not use the official API of android, that could change over android versions and roms.
The question
What's the best way to check if a given app (package name) has admin rights?
What's the best way to go to the admin page ? is there a safer way to go there? maybe a fallback mechanism from what i've done to the security screen intent (which for some reason I can't find in the API) ?
The answer
After reading the answer on this post, I've decided to share the findings:
If you wish to be safe, you can tell the user to go to the admin screen by himself, and only guide him to the security screen:
intent=new Intent(Settings.ACTION_SECURITY_SETTINGS);
context.startActivity(intent);
however, i think the next way should work for all devices:
Intent intent=new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
final PackageManager packageManager=context.getPackageManager();
final List<ResolveInfo> resolveInfos=packageManager.queryIntentActivities(intent,0);
if(resolveInfos!=null&&!resolveInfos.isEmpty())
try
{
final ResolveInfo resolveInfo=resolveInfos.get(0);
intent=new Intent();
intent.setComponent(new ComponentName(resolveInfo.activityInfo.packageName,resolveInfo.activityInfo.name));
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,componentNameResult);
context.startActivity(intent);
return true;
}
catch(final Exception e)
{}
and if it fails, you can always use any of the methods i've written, and in the end, call the safe one.