android - 如何验证 Android DevicePolicyManager#isAdminActive 与未能激活设备管理器的结果

标签 android android-for-work

我面临一个有趣的情况,但我不知道如何解决。当用户作为 Android for Work 用户首次登录我的应用程序时,我有义务确保该应用程序已注册为设备管理器。我通过调用 DevicePolicyManager#isAdminActive 来检查是否是这种情况,如果返回 false,那么我会启动一个带有 action 的 Intent =DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN,以启动启用设备管理的 Android 控件。一旦发生这种情况,当我的应用程序再次启动时(或当它从设备管理流程返回时),将再次检查 DevicePolicyManager#isAdminActive 的值。如果用户启用了设备管理,那么一切都很好,应用会继续运行。

有趣的是,这在用户第一次浏览我们的流程时完全符合预期。不幸的是,在重新启动后,当用户启动我的应用程序时,它会通过 DevicePolicyManager#isAdminActive 检查以确保设备管理仍然处于打开状态,这很有趣。 DevicePolicyManager#isAdminActive 将报告 false,这是通过查看设备安全设置来验证的。然而,更糟糕的是,尝试启用设备管理将导致以下异常:

W/DeviceAdminAdd: Exception trying to activate admin ComponentInfo{com.mysoft.myapp/com.mysoft.core.receivers.MyAppAdminReceiver} java.lang.IllegalArgumentException: Admin is already added at android.os.Parcel.readException(Parcel.java:1550) at android.os.Parcel.readException(Parcel.java:1499) at android.app.enterprise.IEnterpriseDeviceManager$Stub$Proxy.setActiveAdmin(IEnterpriseDeviceManager.java:867) at android.app.enterprise.EnterpriseDeviceManager.setActiveAdmin(EnterpriseDeviceManager.java:720) at com.android.settings.DeviceAdminAdd.addAndFinish(DeviceAdminAdd.java:346) at com.android.settings.DeviceAdminAdd$3.onClick(DeviceAdminAdd.java:313) at android.view.View.performClick(View.java:5242) at android.widget.TextView.performClick(TextView.java:10571) at android.view.View$PerformClick.run(View.java:21196) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:145) at android.app.ActivityThread.main(ActivityThread.java:6938) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at ...

即使我尝试通过系统安全设置页面手动启用设备管理,我的 logcat 控制台上也会出现这个确切的异常,因此我认为原始 Intent 格式不正确。

所以,这是我的问题:对 Android 设备管理 API 的一次调用告诉我我的设备管理员未激活,但对同一 API 的另一次调用告诉我它是。我相信第二个实际上是错误的,但由于无法激活管理,我的用户陷入了循环,无法使用我的应用程序。

有没有其他人遇到过这个错误,如果遇到过,您如何编写代码来解决这个问题?

最佳答案

我分析了DevicePolicyManagerService.java的AOSP源码。功能 在这种情况下失败的调用是 setActiveAdmin(),它会抛出一个 异常,因为它声称我们的应用程序已被添加为设备 行政人员。调用后从 setActiveAdmin 抛出此异常 getActiveAdminUncheckedLocked() 返回一个有效的对象,表示 请求的设备管理员处于 Activity 状态:

final ActiveAdmin existingAdmin
    = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
if (!refreshing && existingAdmin != null) {
    throw new IllegalArgumentException("Admin is already added");
}
if (policy.mRemovingAdmins.contains(adminReceiver)) {
    throw new IllegalArgumentException(
            "Trying to set an admin which is being removed");
}

不过,在此之前,我们已经调用了DevicePolicyManager.isAdminActive, 其中包含以下逻辑:

return getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null;

这很好;这正是我们想要的。但是,这是 AOSP 代码。我推测受影响的可能有不同的实现 设备,其中存在逻辑错误 DevicePolicyManager#isAdminActive(),以便调用在调用时返回 false 应该返回 true。

在生产中部署检测工具来捕获这种情况后,我已经验证了这个假设是正确的。从我的指标推断,Android 设备群体中存在这样的实现,即 isAdminActive(X) 返回的值将返回 false,即使 X将在 getActiveAdmins() 返回的枚举 Activity 管理员列表中找到。幸运的是,这种情况并不常见,但确实存在。我会建议任何依赖这些调用的编码人员针对这种情况强化他们的代码。

关于android - 如何验证 Android DevicePolicyManager#isAdminActive 与未能激活设备管理器的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48572520/

相关文章:

android - 配置设备所有者和 CosuApp

带有图像的 Android 应用程序崩溃

android - 当键盘调整窗口大小时,显示和隐藏键盘会导致延迟

android重复提供者权限

android - 像平行空间一样运行多个android应用程序实例

android - Android Lollipop 中应用程序外部配置文件和内部配置文件之间的数据传输

java - 如何在用户单击 autocom 时显示 HashMap 键的值

java - android - eclipse android launch 卡在 100

android - Airwatch 安卓实现

google-play - 通过 Android Management Api 或设备所有者 locktask 开发 Cosu 应用程序