Android系统的设备管理器功能在一定程度上可以阻止app被卸载。一旦某个app申请了系统设备管理器权限,并且被用户授予了此权限,那么用户必须先取消该app的此项权限才能卸载这个app。(此功能并不适用于所有机型,比如小米或者某些Android 6.0以上的华为手机。)
App在申请了设备管理器权限时,可以调用如下方法打开设备管理器页面:
public static void startDeviceManager(Context mContext) {
//添加一个隐式意图,完成设备权限的添加
//这个Intent (DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN)跳转到 权限提醒页面
//并传递了两个参数EXTRA_DEVICE_ADMIN 、 EXTRA_ADD_EXPLANATION
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
ComponentName componentName = new ComponentName(mContext, ActivateDeviceAdminReceiver.class);
//权限列表
//EXTRA_DEVICE_ADMIN参数中说明了用到哪些权限,
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName);
//描述(additional explanation)
//EXTRA_ADD_EXPLANATION参数为附加的说明
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "");
// intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
((Activity) mContext).startActivityForResult(intent, 0);
}
其中上面代码中的ActivateDeviceAdminReceiver是一个自定义的BroadcastReceiver,必须继承于android.app.admin.DeviceAdminReceiver。在Mainfest中注册如下:
<receiver
android:name=".receiver.ActivateDeviceAdminReceiver"
android:description="@string/description" 这里的字符串会出现在设备管理器激活页面
android:label="@string/app_name"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/device_admin" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
在ActivateDeviceAdminReceiver中,我们可以覆盖父类的onEnable(),onDisable()等方法,用于处理设备管理器被开启或者关闭等情况。
打开的页面类似如下:
但经实验发现,如果用户未为app开启设备管理器功能,那么调用上面的startDeviceManager()方法是可以打开设备管理器页面的。但是一旦开启开启设备管理器功能之后,就无法打开了。这是为什么呢?
看源码注释:
* <p>If your administrator is already active, this will ordinarily return immediately (without
* user intervention). However, if your administrator has been updated and is requesting
* additional uses-policy flags, the user will be presented with the new list. New policies
* will not be available to the updated administrator until the user has accepted the new list.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_ADD_DEVICE_ADMIN
= "android.app.action.ADD_DEVICE_ADMIN";
大概意思就是说,如果设备管理器权限已经打开了的话,想调用这个ACTION_ADD_DEVICE_ADMIN类型的Intent去打开设备管理器页面,是不行的,系统会在没有任何提示的情况下立即返回(即如果调用startActivityForResult()去打开设备管理器页面的话,onActivityResult()方法会立即被调用,并且经验证,返回的resultCode为0)。
另外注意:设备管理器页面必须从activity中打开,如果从Service中打开是不行的。