Android App不被手动强制停止和卸载的实现

您所在的位置:网站首页 安卓强行停止有用吗 Android App不被手动强制停止和卸载的实现

Android App不被手动强制停止和卸载的实现

2024-06-16 12:46| 来源: 网络整理| 查看: 265

最近在做项目时,遇到一个这样的问题,如何让我们的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