【问题标题】:Programmatically deactivate a Device Admininstrator in Android?以编程方式停用 Android 中的设备管理员?
【发布时间】:2013-11-23 08:46:00
【问题描述】:

是否可以以编程方式停用(第三方)Device Administrator 应用程序?

我能够使用DevicePolicyManagergetActiveAdmins() 激活设备管理员检索所有应用程序:

final DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
final List<ComponentName> adminList = dpm.getActiveAdmins();

for ( ComponentName app : adminList ) {
    Log.d(TAG, "App: ", app.getPackageName());
}

但是,为了停用它们,我不能使用removeActiveAdmin(...),因为它不会删除不是我自己的应用程序的组件。

我正在考虑使用 IntentstartActivity() 来打开我要停用的特定组件的设备管理员停用页面。有可能吗?

【问题讨论】:

    标签: android android-intent uninstallation device-admin


    【解决方案1】:

    实际上,可以直接进入管理屏幕,但我不确定它有多安全,因为 API 本身不可用,并且路径可能会随着不同的 android 版本和 rom 而改变。

    这是我测试过的:

    这将直接进入您选择的应用的激活/停用屏幕:

    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);
    

    这将进入管理应用列表:

    final Intent intent=new Intent();
    intent.setComponent(new ComponentName("com.android.settings","com.android.settings.DeviceAdminSettings"));
    activity.startActivity(intent);
    

    如果有人有更官方、更安全的方法,请写下来。

    这些风险很大,所以你可以先用这个方法:

    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)
        {}
    

    你可以为每个方法添加try-catch,如果都失败了,使用:

    final Intent intent=new Intent(Settings.ACTION_SECURITY_SETTINGS);
    activity.startActivity(intent);
    

    【讨论】:

    • 感谢您的回答。正如您所说,使用固定路径并不是一个好习惯。但是,正如您所建议的,我可以使用 try-catch 块来捕获可能的 ActivityNotFoundException 异常。
    • 哦.. 我刚刚发现,在某些情况下,Settings.ACTION_SECURITY_SETTINGS 活动也可能不存在。 developer.android.com/reference/android/provider/…
    • @PaoloRovelli 我现在添加了一种更安全的方法。
    • @PaoloRovelli 真的吗?诡异的。所以应该有另一个后备,去设备的设置?
    • 不确定。也许它不仅仅存在于旧设备上。无论如何,您还需要对 Settings.ACTION_SECURITY_SETTINGS 使用 try-catch 块 (ActivityNotFoundException)。
    【解决方案2】:

    是否可以通过编程方式停用(第三方)设备管理员应用程序?

    没有。也不可能以编程方式激活一个。

    我正在考虑使用 Intent 和 startActivity() 来打开我要停用的特定组件的设备管理员停用页面。

    设置应用程序中没有直接进入删除设备管理屏幕的入口点,更不用说记录在案的Intent 操作了。您可以通过这种方式添加设备管理员,但不能将其删除。

    【讨论】:

    • android.googlesource.com/platform/frameworks/base/+/master/core/…@Commonsware 你可以查看上面的链接吗?它有一种方法可以删除其他应用程序的管理员。方法处于隐藏模式。虽然我使用反射模式来使用该方法,但它给出了 NoSuchMethodException。
    • “它有一种方法可以删除其他应用程序的管理员”——这不是我所看到的。 “但它给出了 NoSuchMethodException”——您可能在旧设备上运行,因为您的链接指向 master 分支。如果该方法存在,我希望你得到一个SecurityException
    【解决方案3】:

    这应该可行:

       ComponentName devAdminReceiver = new ComponentName(context, deviceAdminReceiver.class);
       DevicePolicyManager dpm = (DevicePolicyManager)context.getSystemService(Context.DEVICE_POLICY_SERVICE);
       dpm.removeActiveAdmin(devAdminReceiver);
    

    您需要将其添加到您的活动意图过滤器的清单中:

    <action android:name="android.app.action.DEVICE_ADMIN_DISABLED" />
    

    【讨论】:

    • 根据 Android 文档,您只能停用来自您的应用程序的组件,而不能停用来自第三方应用程序的组件。 developer.android.com/reference/android/app/admin/… 删除当前管理组件。这只能由拥有管理组件的应用程序调用;如果您尝试删除其他人的组件,则会引发安全异常。
    猜你喜欢
    • 2011-08-09
    • 2013-06-05
    • 2023-03-18
    • 2010-10-06
    • 2012-03-07
    • 1970-01-01
    • 2012-05-21
    • 2014-07-02
    • 2011-05-31
    相关资源
    最近更新 更多