一、概述
DevicePolicyManager API可管理和操作设备,使用这个API你可以接管手机的应用权限,比如锁屏,恢复出厂设置,还有设置密码、强制清除密码,修改密码、设置屏幕灯光渐暗时间间隔等操作。
二、客户需求
1.需要三方应用调用setDeviceOwner() .
2.使用反射方法调用,如下图:
三、解题步骤
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);
尝试该方案得到如下结果:
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) {
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) {
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);
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 {
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) {
android.util.Log.i(TAG, "setDeviceOwner e:" + e.toString());
mDPM.removeActiveAdmin(mDeviceAdmin.getComponent());
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
|