Android App不被手动强制停止和卸载的实现 |
您所在的位置:网站首页 › 安卓强行停止有用吗 › Android App不被手动强制停止和卸载的实现 |
最近在做项目时,遇到一个这样的问题,如何让我们的App在“系统设置”里面,不被手动强制停止和卸载? 首先,我们分析一下: - 要实现不被手动停止,必须让系统设置的App详情页面的“强制停止”按钮被置灰才能做到。 - 要实现不被手动卸载,必须让App 获取系统的设备管理权限。 要实现以上两点,我们必须想办法让App在启动时自动获取系统的设备管理权限。接下来,我们通过查阅相关资料,需要按照以下步骤来做: 第一步:实现一个广播监听器,继承DeviceAdminReceiver。如下: public class MyAdminReceiver extends DeviceAdminReceiver { private static final String TAG = "CustomAdminReceiver"; @Override public void onReceive(Context context, Intent intent) { super.onReceive(context, intent); } @Override public void onEnabled(Context context, Intent intent) { super.onEnabled(context, intent); } @Override public void onDisabled(Context context, Intent intent) { // onDisabled } } 第二步:在工程的res目录下,创建xml目录,在xml目录下创建my_admin.xml文件,具体内容如下:
第三步:在AndroidManifest.xml清单文件,添加以下内容: 第四步:创建DeviceAdminUtil类,主要是做相关初始化,设备管理权限获取等。具体如下: public class DeviceAdminUtil { private static DeviceAdminUtil instance; private DevicePolicyManager devicePolicyManager; private ComponentName componentName; private Context mContext; public static synchronized DeviceAdminUtil getInstance() { if (instance == null) { instance = new DeviceAdminUtil(); } return instance; } /** * 初始化“设备管理权限的获取” * * @param context */ public void init(Context context) { mContext = context.getApplicationContext(); // 获取系统管理权限 devicePolicyManager = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); // 申请权限 componentName = new ComponentName(mContext, MyAdminReceiver.class); } /** * 判断App是否已激活获取了设备管理权限,true:已激活,false:未激活 * * @return */ private boolean isAdminActive() { // 判断组件是否有系统管理员权限 return devicePolicyManager.isAdminActive(componentName); } public void lockScreen() { if (isAdminActive() && devicePolicyManager != null) { // 立刻锁屏 devicePolicyManager.lockNow(); } } }经过上述4步操作,已基本实现我们当初的想法。现在我们来验证下。 首先:那我们在App的Application的onCreate方法调用 DeviceAdminUtil.getInstance().init(this);然后,再某一个按钮点击事件里,调用 DeviceAdminUtil.getInstance().lockScreen();接下来,我们运行下App,点击那个按钮并没有锁屏,在系统设置的App详情页面,我们也发现App还是可以手动强制停止,还是可以手动卸载。怎么回事呢? 我们调试发现,做了上述4步,devicePolicyManager.isAdminActive(componentName)这个方法返回仍是false,也就是说App并没有被激活。原因找到了,我们就要想办法激活App。我们查阅DevicePolicyManager的源码,里面有很多方法,其中有一个方法如下: /** * @hide */ public void setActiveAdmin(@NonNull ComponentName policyReceiver, boolean refreshing) { setActiveAdmin(policyReceiver, refreshing, myUserId()); } 这个方法就是激活App获取设备管理权限的方法,但被@hide了,也就是说这个方法只有系统源码层才能直接调用,应用层不能直接调用。到这里,有经验的小伙伴应该会想到,用反射来调用setActiveAdmin方法,实现如下: private void setDeviceAdminActive(boolean active) { try { if (devicePolicyManager != null && componentName != null) { Method setActiveAdmin = devicePolicyManager.getClass().getDeclaredMethod("setActiveAdmin", ComponentName.class, boolean.class); setActiveAdmin.setAccessible(true); setActiveAdmin.invoke(devicePolicyManager, componentName, active); } } catch (Exception e) { LogUtil.e(e); } } 这里给出DeviceAdminUtil类的最终实现,如下: public class DeviceAdminTool { private static DeviceAdminUtil instance; private DevicePolicyManager devicePolicyManager; private ComponentName componentName; private Context mContext; public static synchronized DeviceAdminUtil getInstance() { if (instance == null) { instance = new DeviceAdminUtil(); } return instance; } /** * 初始化“设备管理权限的获取” * * @param context */ public void init(Context context) { mContext = context.getApplicationContext(); // 获取系统管理权限 devicePolicyManager = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); // 申请权限 componentName = new ComponentName(mContext, MyAdminReceiver.class); setDeviceAdminActive(true); } /** * 判断App是否已激活获取了设备管理权限,true:已激活,false:未激活 * app预装,启动后要授权静默激活 * * @return */ private boolean isAdminActive() { // 判断组件是否有系统管理员权限 return devicePolicyManager.isAdminActive(componentName); } public void lockScreen() { if (isAdminActive() && devicePolicyManager != null) { // 立刻锁屏 devicePolicyManager.lockNow(); } } private void setDeviceAdminActive(boolean active) { try { if (devicePolicyManager != null && componentName != null) { Method setActiveAdmin = devicePolicyManager.getClass().getDeclaredMethod("setActiveAdmin", ComponentName.class, boolean.class); setActiveAdmin.setAccessible(true); setActiveAdmin.invoke(devicePolicyManager, componentName, active); } } catch (Exception e) { LogUtil.e(e); } } }以上,在Android7.1,Android8.1上测试有效。 大家如果有好的建议,请留言交流,谢谢~~ 本文章已同步发表在此技术公众号,欢迎大家关注,转发。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |