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

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

个人感觉首先应该看看: Device Administration API,然后在看其他人的理解
先学习API完成项目的功能需求吧;
先预览一下几个相关的Android系统SDK提供的类吧:
Device Administration API
**通过DevicePolicyManager实现息屏代码流程:

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

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

package br.com.tectoy.ttlauncher;

import android.app.admin.DeviceAdminReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

/**
 * @author liuw
 */
public class DeviceReceiver extends DeviceAdminReceiver {
    @Override
    public void onEnabled(Context context, Intent intent) {
        // TODO Auto-generated method stub
        Log.e("TAG000","------onEnabled-------");

        super.onEnabled(context, intent);
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub
        Log.e("TAG000","--------onReceive-----");

        super.onReceive(context, intent);
    }

}

DeviceAdminReceiver类的实现:
AdminReciver继承DeviceAdminReceiver 在mainfest中添加配置:

<receiver
            android:name=".DeviceReceiver"
            android:exported="false"
            android:permission="android.permission.BIND_DEVICE_ADMIN">
            <meta-data android:name="android.app.device_admin"
                android:resource="@xml/device_admin" />
            <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-data的name为:android.app.device_admin【系统中读取配置文件的key固定的】;

可申请的设备管理Iitem的XML文件格式如下

<?xml version="1.0" encoding="utf-8"?>
<device-admin
    xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-policies>
        <limit-password />
        <!-- 限制密码类型 -->
        <watch-login />
        <!-- 监控登录尝试 -->
        <reset-password />
        <!-- 重置密码 -->
        <force-lock />
        <!--锁屏 -->
        <wipe-data />
        <!-- 恢复出厂设置 -->
    </uses-policies>
</device-admin>

申请设备管理权限:

package br.com.tectoy.ttlauncher;

import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import java.lang.reflect.Method;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private static final String MODULE_ICC = "ICC";
    private static final String MODULE_MAG = "MAG";
    private static final String MODULE_PICC = "PICC";
    private static final String MODULE_PRINTER = "PRINTER";
    private static final String MODULE_SCANNER = "SCANNER";
    private static final String MODULE_PED = "PED";
    private DevicePolicyManager mDevicePolicyManager;
    private ComponentName mAdmin;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mDevicePolicyManager = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
        mAdmin = new ComponentName(this, DeviceReceiver.class);
        if(mDevicePolicyManager.isAdminActive(mAdmin)){
            Toast.makeText(MainActivity.this, "已经注册", Toast.LENGTH_LONG).show();
        }else{
            ActiveMNG();
        }
    }
    private void ActiveMNG(){
        Intent intent = new Intent (DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
        intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mAdmin);
        intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,"--其他描述--");
        startActivityForResult(intent , 0 );
    }

    boolean mFlag = true;
    public void setUninstallBlocked(View view) {
        mDevicePolicyManager.setUninstallBlocked(mAdmin, "com.example.liuw.camera2demo", mFlag);
        Toast.makeText(this,"setUninstallBlocked mFlag :"+mFlag,Toast.LENGTH_SHORT).show();
        mFlag = !mFlag;
    }

    public void isUninstallBlocked(View view) {
        boolean uninstallBlocked = mDevicePolicyManager.isUninstallBlocked(mAdmin, "com.example.liuw.camera2demo");
        Toast.makeText(this, "uninstallBlocked :" + uninstallBlocked, Toast.LENGTH_SHORT).show();
    }

    public void setApplicationHidden(View view) {
        boolean setApplicationHidden = mDevicePolicyManager.setApplicationHidden(mAdmin, "com.example.liuw.camera2demo", mFlag);
        Toast.makeText(this, "setApplicationHidden :" + setApplicationHidden +" ,mFlag :"+mFlag, Toast.LENGTH_SHORT).show();
        mFlag = !mFlag;
    }

    public void isApplicationHidden(View view) {
        boolean isApplicationHidden = mDevicePolicyManager.isApplicationHidden(mAdmin, "com.example.liuw.camera2demo");
        Toast.makeText(this, "isApplicationHidden :" + isApplicationHidden, Toast.LENGTH_SHORT).show();
    }

    public void setLockTaskPackages(View view) {
        mDevicePolicyManager.setLockTaskPackages(mAdmin,new String[]{"br.com.tectoy.ttlauncher"});
        Log.w(TAG,"set setLockTaskPackages success!");
    }

    public void disableModule(View view) {
        Class<DevicePolicyManager> devicePolicyManagerClass = DevicePolicyManager.class;
        try {
            Method disableModule = devicePolicyManagerClass.getDeclaredMethod("disableModule", String.class, boolean.class);
            disableModule.setAccessible(true);
            boolean disableModuleResult = (boolean) disableModule.invoke(mDevicePolicyManager, MODULE_ICC, mFlag);
            boolean disableModuleResult2 = (boolean) disableModule.invoke(mDevicePolicyManager, MODULE_MAG, mFlag);
            boolean disableModuleResult3 = (boolean) disableModule.invoke(mDevicePolicyManager, MODULE_PICC, mFlag);
            boolean disableModuleResult4 = (boolean) disableModule.invoke(mDevicePolicyManager, MODULE_PRINTER, mFlag);
            boolean disableModuleResult5 = (boolean) disableModule.invoke(mDevicePolicyManager, MODULE_SCANNER, mFlag);
            boolean disableModuleResult6 = (boolean) disableModule.invoke(mDevicePolicyManager, MODULE_PED, mFlag);

            Toast.makeText(this, "disableModuleResult :" + disableModuleResult +" ,mFlag :"+mFlag, Toast.LENGTH_SHORT).show();
            mFlag = !mFlag;
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "Call disableModule failed :" + e);
        }
    }

    public void getModuleStatus(View view) {
        Class<DevicePolicyManager> devicePolicyManagerClass = DevicePolicyManager.class;
        try {
            Method getModuleStatus = devicePolicyManagerClass.getDeclaredMethod("getModuleStatus",String.class);
            getModuleStatus.setAccessible(true);
            boolean getModuleStatusResult = (boolean) getModuleStatus.invoke(mDevicePolicyManager, MODULE_ICC);
            Log.w(TAG, "getModuleStatusResult :" + getModuleStatusResult);
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "Call getModuleStatus failed :" + e);
        }
    }

    public void lockScreen(View view){
        mDevicePolicyManager.lockNow();

    }
}

贴上build.gradle文件

plugins {
    id 'com.android.application'
}

android {
    compileSdkVersion 33
    buildToolsVersion "30.0.3"

    defaultConfig {
        applicationId "br.com.tectoy.ttlauncher"
        minSdkVersion 22
        targetSdkVersion 32
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {

    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'com.google.android.material:material:1.6.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}

主界面布局文件 button也默认配置好

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    tools:context=".MainActivity">


    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="setUninstallBlocked"
        android:text="setUninstallBlocked"
        android:textAllCaps="false" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="isUninstallBlocked"
        android:text="isUninstallBlocked"
        android:textAllCaps="false" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="setApplicationHidden"
        android:text="setApplicationHidden"
        android:textAllCaps="false" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="isApplicationHidden"
        android:text="isApplicationHidden"
        android:textAllCaps="false" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="setLockTaskPackages"
        android:text="setLockTaskPackages"
        android:textAllCaps="false" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="disableModule"
        android:text="disableModule"
        android:textAllCaps="false" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="getModuleStatus"
        android:text="getModuleStatus"
        android:textAllCaps="false" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="lockScreen"
        android:text="lockScreen"
        android:textAllCaps="false" />

</LinearLayout>

项目的build.gradle文件

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:4.1.2"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

Manifest需要配置的权限

 <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"
  />
    <uses-permission android:name="android.permission.WRITE_APN_SETTINGS"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值