踩一踩 Android 移除 deviceowner 和设备管理器的坑

1. 问题描述:

Android 7.0 上先后执行 clearDeviceOwnerApp(String packageName) 和 设备管理器之后,发现再重新激活设备管理器的时候,会抛出异常:

1
2
3
4
5
6
7
Caused by: java.lang.IllegalArgumentException: Trying to set an admin which is being removed
at android.os.Parcel.readException(Parcel.java:1687)
at android.os.Parcel.readException(Parcel.java:1636)
at com.gionee.mdm.IGnMdmManager$Stub$Proxy.setActiveAdmin(IGnMdmManager.java:1228)
at com.gionee.mdm.GnMdmManager.setActiveAdmin(GnMdmManager.java:538)
at cm.android.mdm.interfaces.IDeviceManagerImpl.setActiveAdmin(IDeviceManagerImpl.java:36)
at java.lang.reflect.Method.invoke(Native Method)

2. 分析问题原因:

问题造成的原因看日志大概就是激活设备管理器的时候,但设备管理器已经移除了。
经过一番分析后,发现在 7.0 设备上执行 clearDeviceOwnerApp(String packageName) 方法的同时也会去自动调用 removeActiveAdmin(ComponentName admin) 方法,
在 7.0 以下设备上,执行 cleardeviceowner() 的方法不会去调用 removeActiveAdmin(ComponentName admin) 方法,因此,在 7.0 设备上移除 deviceowner 后再去调用 removeActiveAdmin(ComponentName admin) 方法时,会导致一直在移除中,从而无法再次激活设备管理器。

3.解决方法:

1) 根据 Android os 版本号来判断是否需要手动调用 removeActiveAdmin(ComponentName admin) 方法;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
DevicePolicyManager policyManager = (DevicePolicyManager) getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName component = new ComponentName(getActivity(), AdminReceiver.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
if (policyManager.isDeviceOwnerApp(getActivity().getPackageName())) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
policyManager.clearDeviceOwnerApp(getActivity().getPackageName());
//在 7.0 以下设备手动调用 removeActiveAdmin 方法
if (!(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)) {
policyManager.removeActiveAdmin(component);
}
}
}
}
2)在移除设备管理器之前判断其是否在移除中,若不在移除中,则执行 removeActiveAdmin(ComponentName admin) 方法;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
DevicePolicyManager policyManager = (DevicePolicyManager) getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
if (policyManager.isDeviceOwnerApp(getActivity().getPackageName())) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
policyManager.clearDeviceOwnerApp(getActivity().getPackageName());
}
}
}
ComponentName component = new ComponentName(getActivity(), AdminReceiver.class);
try {
Method isRemoving = Class.forName("android.app.admin.DevicePolicyManager").getDeclaredMethod("isRemovingAdmin", ComponentName.class, int.class);
isRemoving.setAccessible(true);
boolean isRemove = (boolean) isRemoving.invoke(policyManager, component, 0);
logger.error("ggg clear isRemove = " + isRemove);
if (!isRemove) {
//若设别管理器不在移除中,则移除
policyManager.removeActiveAdmin(component);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}

至此,该坑已经填完!

坚持原创技术分享,您的支持将鼓励我继续创作!