Android设备管理器DevicePolicyManager的使用和理解

上周项目中有个在apk上层实现息屏亮屏的需求,刚开始在网上看到是DevicePolicyManager来实现的,虽然最后根据自己项目特定的环境下并没有使用DevicePolicyManager这个类去实现息屏功能,但看到很多有意思的API值的学习;以备不时之需。

JUST DO IT

至于在Android设计之魅力现在还来不及膜拜;
个人感觉首先应该看看: Device Administration API,然后在看其他人的理解
关于android的设备管理器-DevicePolicyManager(一)
关于android的设备管理器-DevicePolicyManager(二)
先搞定需求,以后一定会慢慢鉴赏现在只是简单看了一下,今天先学习API完成项目的功能需求吧;
先预览一下几个相关的Android系统SDK提供的类吧:

  • android.app.admin包下的重要3个设备管理器类
Classes function
    DeviceAdminInfo
指定设备管理员组件的元信息(可以理解为系统为用户提供可申请设备管理权限信息的JavaBean)
    DeviceAdminReceiver
BroadcastReceiver用以”设置参数”和接受系统返回的管理员权限申请结果;
    DevicePolicyManager
对开发者提供设备操作的API类-

通过DevicePolicyManager实现息屏代码流程:
1. 获的DevicePolicyManager的实例:
2. 申请设备管理权限;
3. 调用DevicePolicyManager的API,完成息屏等其他需求得到操作

获取DevicePolicyManager的实例:

获取DevicePolicyManager的实例

private DevicePolicyManager mDevicePolicyManager;

mDevicePolicyManager = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);

通过反射计算出在DevicePolicyManager类中是由103个public static final修饰的常量;251个public 方法,并且它的Field和Method全部是public修饰:这样个人理解为 Google是把这个类完全开放给Android开发者的;

申请设备管理权限:

申请设备管理权限时需要一个ComponentName(Context pkg, Class cls) 实例,需要一个DeviceAdminReceiver的Class;但是DeviceAdminReceiver本身就是一个BroadcastReceiver,于是新建一个AdminReciver类extends DeviceAdminReceiver作为DeviceAdminReceiver实例

DeviceAdminReceiver 的实现和作用:

DeviceAdminReceiver类的实现:
AdminReciver继承DeviceAdminReceiver,作为Android的四大组件之一的BroadcastReceiver所以需要在mainfest中添加配置:

   <!-- 设备管理器权限,注册权限监听器 -->
        <receiver
            android:name=".receiver.AdminReciver"
            android:permission="android.permission.BIND_DEVICE_ADMIN">
            <meta-data
                android:name="android.app.device_admin"
                android:resource="@xml/adminmanager" />

            <intent-filter>
                <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
            </intent-filter>
        </receiver>

其中需要注意的有
android:permission、meta-data、action
重点是:meta-data的配置,在meta-data配置本DeviceAdminReceiver中申请设备管理器的具体权限,
有点类似在mainfest中配置App需要的各个uses-permission权限;
本次配置的mete-dataname为:android.app.device_admin【系统中读取配置文件的key固定的】

可申请的设备管理Iitem的XML文件格式如下【实际开发中可以一次申请全部权限,也可以只申请部分管理者权限,也可以分几次申请,本次分为;两次申请见demo】:

<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-policies>
        <!--锁屏 -->
        <force-lock />
        <!--限制密码类型-->
        <limit-password />
       <!-- 监控屏幕解锁尝试次数 -->
        <watch-login />
        <!-- 重置密码-->
        <reset-password />
        <!--恢复出厂设置-->
        <wipe-data />
        <!-- 设置锁定屏幕密码的有效期 -->
        <expire-password />
        <!-- 设置存储设备加密 -->
        <encrypted-storage />
        <!-- 停用相机 -->
        <disable-camera />
    </uses-policies>
</device-admin>

相信大家也都看到了,AdminRecivermainfestmeta-datadata配置为:
android:resource=”@xml/adminmanager”
也就是在res资源文件夹下新建一个名字为xml的资源文件将adminmanager.xml丢进去就OK了,在申请管理权限时系统会根据我们的配置文件读取我们本次DeviceAdminReceiver需要申请那些具体的权限


AdminReciver extends DeviceAdminReceiver 的作用
相信大多数人和我一样,在第一眼看到DeviceAdminReceiver这个玩意时单纯的把它当做一个系统作为申请管理权限结果的一个通知回调BroadcastReceiver理解了吧;

扫描二维码关注公众号,回复: 1769929 查看本文章

但是看到 申请设备管理者权限代码、isAdminActive()【如下】就发现DeviceAdminReceiver【子类】不仅仅是申请管理权限结果的一个通知回调BroadcastReceiver了:

申请设备管理权限:

准备好申请设备管理权限需要的类和文件后接下来就是具体的实现代码:


  private int requestCode = 1;
  private  ComponentName adminReceiver;
  //AdminReciver.class就是DeviceAdminReceiver的子类
   adminReceiver = new ComponentName(this, AdminReciver.class);

   /**
    *申请设备管理员权限
   */
    private void requestLockAdmins() {
    //检查是否已经获取设备管理权限
        boolean active = mDevicePolicyManager.isAdminActive(adminReceiver);
        if (!active) {
            //打开DevicePolicyManager管理器,授权页面
            Intent intent = new Intent();
            //授权页面Action -->  DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN
            intent.setAction(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
            //设置DEVICE_ADMIN,告诉系统申请管理者权限的Component/DeviceAdminReceiver
            intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, adminReceiver);
            //设置 提示语--可不添加
            intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "DevicePolicyManager涉及的管理权限,一次性激活!");
            startActivityForResult(intent, requestCode);
        } else {
            Toast.makeText(this, "已经获取的DevicePolicyManager管理器的授权", Toast.LENGTH_LONG).show();
        }
    }

  /**
     * 查看是否已经获得管理者的权限
     * @return resualt
     */
    private boolean checkAdmin() {
        return mDevicePolicyManager.isAdminActive(adminReceiver);
    }

先说一下mainfest在apk申请的使用权限【uses-permission】作用吧
当Android安装apk时会自动去默认的路径(可以手动修改mainfest的位置)找到mainfest“扫描”开发者在mainfest申请的使用权限,从而提示用户授权;整个过程mainfest就是存放开发者申请具体uses-permission的一个XML记录便签

adminmanager.xml对于申请设备管理员权限的作用十分类似在apk中申请使用权限【uses-permission】过程中mainfest的作用;
在申请设备管理权限时adminmanager.xml的作用就像mainfest的作用一样就是存放申请设备管理权限的一个XML载体

通过在DeviceAdminReceiver配置meta-data的方式adminmanager.xml的位置信息和DeviceAdminReceiver绑定,然后通过ComponentName 将AdminReciver借助DevicePolicyManager的API传递给Android系统层,Android系统层通过AdminReciver中的meta-data找到adminmanager.xml位置,读出申请设备权限并提示用户授权,然后返回结果


在adminmanager.xml中配置了几个常见的uses-policies设备管理权限在DevicePolicyManager中都有一个对映的方法:

uses-policies Method CN
force-lock public void lockNow() * 锁屏 *
limit-password public void setPasswordQuality(@NonNull ComponentName admin, int quality) 限制密码类型
watch-login public int getCurrentFailedPasswordAttempts() 监控屏幕解锁尝试次数
reset-password public boolean resetPassword(String password, int flags) 重置密码
wipe-data public void wipeData(int flags) 恢复出厂设置
expire-password public void setPasswordExpirationTimeout(@NonNull ComponentName admin, long timeout) 设置锁定屏幕密码的有效期
encrypted-storage public int setStorageEncryption(@NonNull ComponentName admin, boolean encrypt) 设置存储设备加密
disable-camera public void setCameraDisabled(@NonNull ComponentName admin, boolean disabled) 停用相机

以上这些是在百度中最长见到吧,下面介绍几个有趣的API:

API CN API level
public boolean isAdminActive (ComponentName admin) 查看当前管理者(admin)是否拥有管理者权限 8
public List <ComponentName>getActiveAdmins () 获取当前apk拥有设备管理员的DeviceAdminReceiver类的权限列表 8
public boolean getCameraDisabled (ComponentName admin) 查看当前的管理者(admin)是否禁止相机 14
public void setKeyguardDisabledFeatures(ComponentName, int) 设置当前的管理者(admin)禁止使用键盘 0:default;1:禁止 17
public int getKeyguardDisabledFeatures (ComponentName admin) 查看当前的管理者(admin)是否禁止使用键盘,结果同 上 17
public void removeActiveAdmin (ComponentName admin) 撤销管理者(admin)申请的管理者权限 8
public boolean isDeviceOwnerApp (String packageName) 查看某个App是否已经获取管理者权限(packageName目标App包名) 18
public boolean hasGrantedPolicy (ComponentName admin, int usesPolicy) 检查当前管理者(admin)是否拥有usesPolicy项管理者权限usesPolicy参考 DeviceAdminInfo. 11

本次只是初步调用了几个DevicePolicyManager中的方法,如果有其他大家可以异步到:Anroid Device Administration API 查看 Device Administration

猜你喜欢

转载自blog.csdn.net/black_bird_cn/article/details/79735794