我正在开发用于Android的MDM(移动设备管理)应用程序,但我遇到了一个很大的问题,那就是用户可以在设置> security>设备管理员中禁用我的应用程序。我唯一能做的就是通过覆盖onDisableRequested(...)
子类中的DeviceAdminReceiver
方法来显示警告消息,但我真的想阻止用户完全禁用我的管理员应用程序。 / p>
我试图覆盖onReceive(...)
方法,以便在系统广播ACTION_DEVICE_ADMIN_DISABLE_REQUESTED和ACTION_DEVICE_ADMIN_DISABLED操作时没有任何反应,但到目前为止它还没有奏效。显然,其他一些组件在它们到达我的onReceive(...)
方法之前处理这些操作,我不知道为什么。我希望能够显示我自己的自定义对话框,指示用户无法从此部分禁用管理员应用程序,甚至可能要求用户设置管理员密码来执行此操作。
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_PASSWORD_CHANGED.equals(action)) {
onPasswordChanged(context, intent);
} else if (ACTION_PASSWORD_FAILED.equals(action)) {
onPasswordFailed(context, intent);
} else if (ACTION_PASSWORD_SUCCEEDED.equals(action)) {
onPasswordSucceeded(context, intent);
} else if (ACTION_DEVICE_ADMIN_ENABLED.equals(action)) {
onEnabled(context, intent);
} else if (ACTION_DEVICE_ADMIN_DISABLE_REQUESTED.equals(action)) {
} else if (ACTION_DEVICE_ADMIN_DISABLED.equals(action)) {
} else if (ACTION_PASSWORD_EXPIRING.equals(action)) {
onPasswordExpiring(context, intent);
}
}
我需要帮助来解决这个问题。
谢谢,
答案 0 :(得分:6)
您可以使用新的设备所有者模式从Android 5 Lollipop执行此操作。然后灰显的设备管理员选项和用户无法禁用它,因此不会卸载设备管理员应用程序。
但请注意,安装设备所有者应用程序并不容易,必须在配置时使用NFC完成,或者从带有adb的计算机(方便测试但不用于部署)或MDM是什么时候完成你的情况......
答案 1 :(得分:4)
没有办法阻止用户禁用,这是他的权利。
但要确保用户自己实际上已删除管理员权限,请使用其密码将设备锁定在 onDisableRequested 中并返回“有人试图禁用此应用管理员功能”之类的内容。是你吗?你确定吗?“。
现在,如果真实用户以外的其他人尝试禁用它,则必须在继续之前输入密码。
答案 2 :(得分:3)
我同意FoamyGuy,您不能阻止禁用管理员。否则,您的应用程序根本无法卸载。
一般来说,用户授予某些应用程序设备管理员权限,并且可以随时删除这些权利。
任何广播只是通知,您无法处理它并阻止某些操作发生。该系统只是说要听应用程序正在发生的事情。
另外,请阅读:
How to wipe Android device when device admin is deactivated?
答案 3 :(得分:1)
这不是一个很好的方法,但这里有一个想法:
当你收到回调ACTION_DEVICE_ADMIN_DISABLE_REQUESTED时,请终止设置应用。 
(搜索任务杀手以了解具体方法)


并确保在用户输入密码后不要终止settings-app。


如果设置应用程序消失,则用户无法单击禁用按钮。

答案 4 :(得分:1)
有一个解决方法,可以防止禁用设备管理员。
当用户启动停用功能并且我们收到ACTION_DEVICE_ADMIN_DISABLE_REQUESTED回调时,我们将重新启动设置活动意图。
OS允许显示一条消息,要求用户确认。根据Android OS规则,在大约5秒钟内,不允许在此确认对话框顶部启动任何应用程序。因此,基本上,我们尝试打开的设置活动只会在5秒钟后启动。
要在不允许用户确认停用的情况下经过这5秒钟,设备管理员会在后台线程中反复将电话锁定。用户解锁设备5秒钟后,“设置”活动将重新开始。
下面的“设备管理广播接收器类”代码说明了上述方法。
DevAdminReceiver.java
public class DevAdminReceiver extends DeviceAdminReceiver {
DevicePolicyManager dpm;
long current_time;
Timer myThread;
@Override
public void onEnabled(@NonNull Context context, @NonNull Intent intent) {
super.onEnabled(context, intent);
Log.d("Root", "Device Owner Enabled");
}
@Nullable
@Override
public CharSequence onDisableRequested(@NonNull Context context, @NonNull Intent intent) {
Log.d("Device Admin","Disable Requested");
Intent startMain = new Intent(android.provider.Settings.ACTION_SETTINGS);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(startMain);
dpm = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
myThread = new Timer();
current_time = System.currentTimeMillis();
myThread.schedule(lock_task,0,1000);
return "Warning";
}
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_DEVICE_ADMIN_DISABLE_REQUESTED.equals(action)) {
CharSequence res = onDisableRequested(context, intent);
if (res != null) {
dpm.lockNow();
Bundle extras = getResultExtras(true);
extras.putCharSequence(EXTRA_DISABLE_WARNING, res);
}
}else if (ACTION_DEVICE_ADMIN_DISABLED.equals(action)) {
Log.d("Device Admin","Disabled");
}
}
// Repeatedly lock the phone every second for 5 seconds
TimerTask lock_task = new TimerTask() {
@Override
public void run() {
long diff = System.currentTimeMillis() - current_time;
if (diff<5000) {
Log.d("Timer","1 second");
dpm.lockNow();
}
else{
myThread.cancel();
}
}
};
}
确保在资源文件中为设备管理员设置了force lock
策略。
这纯粹是一种解决方法,并不是开发人员的预期解决方案。暴露设备管理员权限的应用在暴露后总是会立即从Play商店中删除。
以下回购中包含完整的示例代码
https://github.com/abinpaul1/Android-Snippets/tree/master/PermanentDeviceAdministrator