以编程方式停用 Android 中的设备管理员?

Posted

技术标签:

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

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

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

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(...),因为它不会删除不是我自己的应用程序的组件。

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

【问题讨论】:

【参考方案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/… 删除当前管理组件。这只能由拥有管理组件的应用程序调用;如果您尝试删除其他人的组件,则会引发安全异常。

以上是关于以编程方式停用 Android 中的设备管理员?的主要内容,如果未能解决你的问题,请参考以下文章

我可以以编程方式配置 PostgreSQL 以不消除全文搜索中的停用词吗?

以编程方式修改 android:exported

以编程方式将设备连接到android中的同一wifi网络?

有没有办法通过 iOS/swift 中的蓝牙以编程方式连接 android 和 IOS 设备?

以编程方式阅读 Android 中的 Sim 联系人?

以编程方式获取 Android 手机型号,如何在 android 中以编程方式获取设备名称和型号?