一、概述

DevicePolicyManager API可管理和操作设备,使用这个API你可以接管手机的应用权限,比如锁屏,恢复出厂设置,还有设置密码、强制清除密码,修改密码、设置屏幕灯光渐暗时间间隔等操作。

二、客户需求

1.需要三方应用调用setDeviceOwner().

2.使用反射方法调用,如下图:

Android 设备管理员_java

三、解题步骤

1.Android系统提供一种方案

代码如下:

Intent intent = new Intent(
  DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
                mComponentName);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "提示文字");
startActivityForResult(intent, 1);

尝试该方案得到如下结果:

Android 设备管理员_java_02

2.分析方案

搜索广播发现在此地方接收广播处理:

路径:

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminAdd.java

代码如下(示例):

if (DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN.equals(getIntent().getAction())) {
    mRefreshing = false;
    if (mDPM.isAdminActive(who)) {
        if (mDPM.isRemovingAdmin(who, android.os.Process.myUserHandle().getIdentifier())) {
            Log.w(TAG, "Requested admin is already being removed: " + who);
            finish();
            return;
        }

        ArrayList<DeviceAdminInfo.PolicyInfo> newPolicies = mDeviceAdmin.getUsedPolicies();
        for (int i = 0; i < newPolicies.size(); i++) {
            DeviceAdminInfo.PolicyInfo pi = newPolicies.get(i);
            if (!mDPM.hasGrantedPolicy(who, pi.ident)) {
                mRefreshing = true;
                break;
            }
        }
        if (!mRefreshing) {
            // Nothing changed (or policies were removed) - return immediately
            setResult(Activity.RESULT_OK);
            finish();
            return;
        }
    }
}

点击同意之后处理的方法:

路径:

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminAdd.java

方法:

void addAndFinish() {
    try {
        logSpecialPermissionChange(true, mDeviceAdmin.getComponent().getPackageName());
        mDPM.setActiveAdmin(mDeviceAdmin.getComponent(), mRefreshing);
        EventLog.writeEvent(EventLogTags.EXP_DET_DEVICE_ADMIN_ACTIVATED_BY_USER,
                            mDeviceAdmin.getActivityInfo().applicationInfo.uid);

        unrestrictAppIfPossible(BatteryUtils.getInstance(this));

        setResult(Activity.RESULT_OK);
    } catch (RuntimeException e) {
        // Something bad happened...  could be that it was
        // already set, though.
        Log.w(TAG, "Exception trying to activate admin "
              + mDeviceAdmin.getComponent(), e);
        if (mDPM.isAdminActive(mDeviceAdmin.getComponent())) {
            setResult(Activity.RESULT_OK);
        }
    }
    if (mAddingProfileOwner) {
        try {
            mDPM.setProfileOwner(mDeviceAdmin.getComponent(),
                                 mProfileOwnerName, UserHandle.myUserId());
        } catch (RuntimeException re) {
            setResult(Activity.RESULT_CANCELED);
        }
    }
    finish();
}

3.结合客户需求

1.新建类WangPosManager

路径:

frameworks/base/core/java/android/os/WangPosManager.java

2.广播接收处理方法并点击同意按钮

代码如下:

public void setDeviceOwner(Context context, ComponentName who) {
    Log.i(TAG, "setDeviceOwner who:" + who.getPackageName());
    mDPM = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
    // mDPM = IDevicePolicyManager.Stub.asInterface(
    //         ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
    PackageManager packageManager = context.getPackageManager();
    ActivityInfo ai;
    try {
        ai = packageManager.getReceiverInfo(who, PackageManager.GET_META_DATA);
    } catch (PackageManager.NameNotFoundException e) {
        Log.w(TAG, "Unable to retrieve device policy " + who, e);
        return;
    }
    if (!mDPM.isAdminActive(who)) {
        Log.i(TAG, "!isAdminActive");
        List<ResolveInfo> avail = packageManager.queryBroadcastReceivers(
            new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED),
            PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
        int count = avail == null ? 0 : avail.size();
        boolean found = false;
        for (int i=0; i<count; i++) {
            ResolveInfo ri = avail.get(i);
            Log.i(TAG, "ri.activityInfo.packageName:" + ri.activityInfo.packageName);
            Log.i(TAG, "ri.activityInfo.name:" + ri.activityInfo.name);
            if (ai.packageName.equals(ri.activityInfo.packageName)
                && ai.name.equals(ri.activityInfo.name)) {
                Log.i(TAG, "ai.packageName:" + ai.packageName);
                Log.i(TAG, "ai.name:" + ai.name);
                try {
                    // We didn't retrieve the meta data for all possible matches, so
                    // need to use the activity info of this specific one that was retrieved.
                    ri.activityInfo = ai;
                    found = true;
                } catch (Exception e) {
                    Log.w(TAG, "Bad " + ri.activityInfo + " e:" + e.toString());
                }
                break;
            }
        }
        if (!found) {
            Log.w(TAG, "Request to add invalid device admin: " + who);
            return;
        }
    }

    ResolveInfo ri = new ResolveInfo();
    ri.activityInfo = ai;
    try {
        mDeviceAdmin = new DeviceAdminInfo(context, ri);
    } catch (XmlPullParserException e) {
        Log.w(TAG, "Unable to retrieve device policy " + who + " e:" + e.toString());
        return;
    } catch (IOException e) {
        Log.w(TAG, "Unable to retrieve device policy " + who + " e:" + e.toString());
        return;
    }
    mDPM.setActiveAdmin(mDeviceAdmin.getComponent(), true, 0);

    try {
        if (!mDPM.setDeviceOwner(mDeviceAdmin.getComponent(), "", 0)) {
            throw new RuntimeException(
                "Can't set package " + mDeviceAdmin.getComponent() + " as device owner.");
        }
    } catch (Exception e) {
        // Need to remove the admin that we just added.
        android.util.Log.i(TAG, "setDeviceOwner e:" + e.toString());
        mDPM.removeActiveAdmin(mDeviceAdmin.getComponent()/*, UserHandle.USER_SYSTEM*/);
        throw e;
    }

    mDPM.setUserProvisioningState(
        DevicePolicyManager.STATE_USER_SETUP_FINALIZED, 0);
}

四、调用方法

1.设置管理员

adminReceiver = new ComponentName(this, "com.example.b3111_pa_demo.AdminReciver");
mDevicePolicyManager = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
setDeviceOwner(adminReceiver);

public void setDeviceOwner(ComponentName componentName) {
  try {
    Class WangPosManagerClass = Class.forName("android.os.WangPosManager");
    Object WangPosManager = WangPosManagerClass.newInstance();
    Method method = WangPosManagerClass.getMethod("setDeviceOwner", Context.class, ComponentName.class);
    method.invoke(WangPosManager, this, componentName);
  } catch (Exception e) {
    Log.i(TAG, "setDeviceOwner exception e:" + e.toString());
  }
}

2.其他

锁屏:mDPM.lockNow();
恢复出厂设置: mDPM.wipeData(0);
屏幕光亮时间间隔:mDPM.setMaximumTimeToLock(mDeviceComponentName, timeout);

五、补充

使用adb命令可直接将三方应用设为、取消设备管理员。

adb shell dpm set-device-owner com.example.b3111_pa_demo/.AdminReciver
adb shell dpm remove-active-admin com.example.b3111_pa_demo/.AdminReciver