从清单文件device_admin.xml说起
AndroidManifest.xml中用法如下
DPMTestReceiver重写DeviceAdminReceiver后
dpm=(DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
admin=new ComponentName(this,DPMTestReceiver.class);
那么一个处于active状态的admin有什么用呢?或者说我们可以用它来做什么?
public void wipeData(int flags) {
if (mService != null) {
try {
mService.wipeData(flags, UserHandle.myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
它有两个flags可选择
//双清存储数据(包括外置sd卡),wipeData后重启
public static final int WIPE_EXTERNAL_STORAGE = 0x0001;
//恢复出厂设置,使用此flag必须是device owner,否则将抛出SecurityException异常,而setDeviceOwner为隐藏API
public static final int WIPE_RESET_PROTECTION_DATA = 0x0002;
//password为空时可清除密码
public boolean resetPassword(String password, int flags) {
if (mService != null) {
try {
return mService.resetPassword(password, flags);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
return false;
}
它有三个flags可选择
//当设置此flag时,resetPassword在锁屏状态下失去重置作用,即任何admin用户都必须先进入系统才能重置密码
public static final int RESET_PASSWORD_REQUIRE_ENTRY = 0x0001;
//使用此flag必须是device owner,可在不需要密码的情况下启动设备,暂不清楚用法
public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 0x0002;
//设为0表示可任意重置密码(无论是否解锁)
public static final int PASSWORD_QUALITY_UNSPECIFIED = 0;
//设置密码最小长度
public void setPasswordMinimumLength(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumLength(admin, length);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
//密码最少需要的字母
public void setPasswordMinimumLetters(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumLetters(admin, length);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
//密码最少需要的小写字母
public void setPasswordMinimumLowerCase(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumLowerCase(admin, length);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
//混合密码最少需要的数字
public void setPasswordMinimumNonLetter(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumNonLetter(admin, length);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
//密码最少需要的数字
public void setPasswordMinimumNumeric(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumNumeric(admin, length);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
//密码最少需要的符号
public void setPasswordMinimumSymbols(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumSymbols(admin, length);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
//密码最少需要的大写字母
public void setPasswordMinimumUpperCase(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumUpperCase(admin, length);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
//设置密码策略(与上述方法相比比较粗略)
public void setPasswordQuality(@NonNull ComponentName admin, int quality) {
if (mService != null) {
try {
mService.setPasswordQuality(admin, quality);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
可使用如下flags
//没有什么特殊规则,但字符串长度不能小于4
public static final int PASSWORD_QUALITY_UNSPECIFIED = 0;
//只能使用PIN码、密码与图案锁,其它不能使用
public static final int PASSWORD_QUALITY_BIOMETRIC_WEAK = 0x8000;
//mtk添加,可以使用PIN码、密码、图案锁与语音解锁
public static final int PASSWORD_QUALITY_VOICE_WEAK = 0x4000;
//只能使用PIN码、密码与图案锁,其它不能使用
public static final int PASSWORD_QUALITY_SOMETHING = 0x10000;
//只能使用PIN码与密码
public static final int PASSWORD_QUALITY_NUMERIC = 0x20000;
//只能使用PIN码与密码,并且PIN码禁止以顺序排列且禁止重复
public static final int PASSWORD_QUALITY_NUMERIC_COMPLEX = 0x30000;
//只能使用密码
public static final int PASSWORD_QUALITY_ALPHABETIC = 0x40000;
//只能使用密码,并且密码至少要包含一个数字
public static final int PASSWORD_QUALITY_ALPHANUMERIC = 0x50000;
//只能使用密码,并且密码至少要包含一个数字和一个特殊字符
public static final int PASSWORD_QUALITY_COMPLEX = 0x60000;
public void setMaximumFailedPasswordsForWipe(@NonNull ComponentName admin, int num) {
if (mService != null) {
try {
mService.setMaximumFailedPasswordsForWipe(admin, num);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
public int getCurrentFailedPasswordAttempts() {
if (mService != null) {
try {
return mService.getCurrentFailedPasswordAttempts(UserHandle.myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
return -1;
}
public void lockNow() {
if (mService != null) {
try {
mService.lockNow();
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
//固定指定应用的屏幕,需要device owner调用,然后调用Activity的startLockTask()方法
public void setLockTaskPackages(@NonNull ComponentName admin, String[] packages)
throws SecurityException {
if (mService != null) {
try {
mService.setLockTaskPackages(admin, packages);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
public void setMaximumTimeToLock(@NonNull ComponentName admin, long timeMs) {
if (mService != null) {
try {
mService.setMaximumTimeToLock(admin, timeMs);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
//设定密码保存的时间
public void setPasswordExpirationTimeout(@NonNull ComponentName admin, long timeout) {
if (mService != null) {
try {
mService.setPasswordExpirationTimeout(admin, timeout);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
//在上述的指定时间内保存多少个密码
public void setPasswordHistoryLength(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordHistoryLength(admin, length);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
public int setStorageEncryption(@NonNull ComponentName admin, boolean encrypt) {
if (mService != null) {
try {
return mService.setStorageEncryption(admin, encrypt);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
return ENCRYPTION_STATUS_UNSUPPORTED;
}
public void setCameraDisabled(@NonNull ComponentName admin, boolean disabled) {
if (mService != null) {
try {
mService.setCameraDisabled(admin, disabled);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
public boolean installCaCert(@Nullable ComponentName admin, byte[] certBuffer) {
if (mService != null) {
try {
return mService.installCaCert(admin, certBuffer);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
return false;
}
public void uninstallCaCert(@Nullable ComponentName admin, byte[] certBuffer) {
if (mService != null) {
try {
final String alias = getCaCertAlias(certBuffer);
mService.uninstallCaCerts(admin, new String[] {alias});
} catch (CertificateException e) {
Log.w(TAG, "Unable to parse certificate", e);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
public List getInstalledCaCerts(@Nullable ComponentName admin) {
List certs = new ArrayList();
if (mService != null) {
try {
mService.enforceCanManageCaCerts(admin);
final TrustedCertificateStore certStore = new TrustedCertificateStore();
for (String alias : certStore.userAliases()) {
try {
certs.add(certStore.getCertificate(alias).getEncoded());
} catch (CertificateException ce) {
Log.w(TAG, "Could not encode certificate: " + alias, ce);
}
}
} catch (RemoteException re) {
Log.w(TAG, "Failed talking with device policy service", re);
}
}
return certs;
}
public void uninstallAllUserCaCerts(@Nullable ComponentName admin) {
if (mService != null) {
try {
mService.uninstallCaCerts(admin, new TrustedCertificateStore().userAliases()
.toArray(new String[0]));
} catch (RemoteException re) {
Log.w(TAG, "Failed talking with device policy service", re);
}
}
}
同一时间只能有一个Device Owner,需要权限MANAGE_PROFILE_AND_DEVICE_OWNERS,shell uid可以调用
//设置后无法从settings取消
public void setAutoTimeRequired(@NonNull ComponentName admin, boolean required) {
if (mService != null) {
try {
mService.setAutoTimeRequired(admin, required);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
//@deprecated From {@link android.os.Build.VERSION_CODES#M
public UserHandle createUser(@NonNull ComponentName admin, String name) {
try {
return mService.createUser(admin, name);
} catch (RemoteException re) {
Log.w(TAG, "Could not create a user", re);
}
return null;
}
//@deprecated From {@link android.os.Build.VERSION_CODES#M
public UserHandle createAndInitializeUser(@NonNull ComponentName admin, String name,
String ownerName, @NonNull ComponentName profileOwnerComponent, Bundle adminExtras) {
try {
return mService.createAndInitializeUser(admin, name, ownerName, profileOwnerComponent,
adminExtras);
} catch (RemoteException re) {
Log.w(TAG, "Could not create a user", re);
}
return null;
}
//@deprecated From {@link android.os.Build.VERSION_CODES#M
public boolean removeUser(@NonNull ComponentName admin, UserHandle userHandle) {
try {
return mService.removeUser(admin, userHandle);
} catch (RemoteException re) {
Log.w(TAG, "Could not remove user ", re);
return false;
}
}
//@deprecated From {@link android.os.Build.VERSION_CODES#M
public boolean switchUser(@NonNull ComponentName admin, @Nullable UserHandle userHandle) {
try {
return mService.switchUser(admin, userHandle);
} catch (RemoteException re) {
Log.w(TAG, "Could not switch user ", re);
return false;
}
}
//Called by a device owner or profile owner
public void setAccountManagementDisabled(@NonNull ComponentName admin, String accountType,
boolean disabled) {
if (mService != null) {
try {
mService.setAccountManagementDisabled(admin, accountType, disabled);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
public boolean setKeyguardDisabled(@NonNull ComponentName admin, boolean disabled) {
try {
return mService.setKeyguardDisabled(admin, disabled);
} catch (RemoteException re) {
Log.w(TAG, "Failed talking with device policy service", re);
return false;
}
}
public void setRecommendedGlobalProxy(@NonNull ComponentName admin, @Nullable ProxyInfo
proxyInfo) {
if (mService != null) {
try {
mService.setRecommendedGlobalProxy(admin, proxyInfo);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
public boolean setStatusBarDisabled(@NonNull ComponentName admin, boolean disabled) {
try {
return mService.setStatusBarDisabled(admin, disabled);
} catch (RemoteException re) {
Log.w(TAG, "Failed talking with device policy service", re);
return false;
}
}
/**
* Callable by the system update service to notify device owners about pending updates.
* The caller must hold {@link android.Manifest.permission#NOTIFY_PENDING_SYSTEM_UPDATE}
* permission.
*
* @param updateReceivedTime The time as given by {@link System#currentTimeMillis()} indicating
* when the current pending update was first available. -1 if no update is available.
* @hide
*/
@SystemApi
public void notifyPendingSystemUpdate(long updateReceivedTime) {
if (mService != null) {
try {
mService.notifyPendingSystemUpdate(updateReceivedTime);
} catch (RemoteException re) {
Log.w(TAG, "Could not notify device owner about pending system update", re);
}
}
}
//需要System UID或者shell uid调用
public boolean setProfileOwner(@NonNull ComponentName admin, @Deprecated String ownerName,
int userHandle) throws IllegalArgumentException {
if (admin == null) {
throw new NullPointerException("admin cannot be null");
}
if (mService != null) {
try {
if (ownerName == null) {
ownerName = "";
}
return mService.setProfileOwner(admin, ownerName, userHandle);
} catch (RemoteException re) {
Log.w(TAG, "Failed to set profile owner", re);
throw new IllegalArgumentException("Couldn't set profile owner.", re);
}
}
return false;
}
//Called by profile or device owners
public boolean setApplicationHidden(@NonNull ComponentName admin, String packageName,
boolean hidden) {
if (mService != null) {
try {
return mService.setApplicationHidden(admin, packageName, hidden);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
return false;
}
public boolean isApplicationHidden(@NonNull ComponentName admin, String packageName) {
if (mService != null) {
try {
return mService.isApplicationHidden(admin, packageName);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
return false;
}
/**
* Called by profile or device owners to re-enable a system app that was disabled by default
* when the user was initialized.
*/
public void enableSystemApp(@NonNull ComponentName admin, String packageName) {
if (mService != null) {
try {
mService.enableSystemApp(admin, packageName);
} catch (RemoteException e) {
Log.w(TAG, "Failed to install package: " + packageName);
}
}
}
public int enableSystemApp(@NonNull ComponentName admin, Intent intent) {
if (mService != null) {
try {
return mService.enableSystemAppWithIntent(admin, intent);
} catch (RemoteException e) {
Log.w(TAG, "Failed to install packages matching filter: " + intent);
}
}
return 0;
}
//Called by profile or device owners to update {@link Settings.Secure} settings.
public void setSecureSetting(@NonNull ComponentName admin, String setting, String value) {
if (mService != null) {
try {
mService.setSecureSetting(admin, setting, value);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
//Called by profile or device owners to set the master volume mute on or off.
public void setMasterVolumeMuted(@NonNull ComponentName admin, boolean on) {
if (mService != null) {
try {
mService.setMasterVolumeMuted(admin, on);
} catch (RemoteException re) {
Log.w(TAG, "Failed to setMasterMute on device policy service");
}
}
}
public boolean isMasterVolumeMuted(@NonNull ComponentName admin) {
if (mService != null) {
try {
return mService.isMasterVolumeMuted(admin);
} catch (RemoteException re) {
Log.w(TAG, "Failed to get isMasterMute on device policy service");
}
}
return false;
}
//Called by profile or device owners to change whether a user can uninstall
public void setUninstallBlocked(@NonNull ComponentName admin, String packageName,
boolean uninstallBlocked) {
if (mService != null) {
try {
mService.setUninstallBlocked(admin, packageName, uninstallBlocked);
} catch (RemoteException re) {
Log.w(TAG, "Failed to call block uninstall on device policy service");
}
}
}
public boolean isUninstallBlocked(@Nullable ComponentName admin, String packageName) {
if (mService != null) {
try {
return mService.isUninstallBlocked(admin, packageName);
} catch (RemoteException re) {
Log.w(TAG, "Failed to call block uninstall on device policy service");
}
}
return false;
}
// Called by profile or device owners to set the current user's photo.
public void setUserIcon(@NonNull ComponentName admin, Bitmap icon) {
try {
mService.setUserIcon(admin, icon);
} catch (RemoteException re) {
Log.w(TAG, "Could not set the user icon ", re);
}
}
//Called by profile or device owners, it only applies to applications
// built with a {@code targetSdkVersion} of {@link android.os.Build.VERSION_CODES#M} or later.
public void setPermissionPolicy(@NonNull ComponentName admin, int policy) {
try {
mService.setPermissionPolicy(admin, policy);
} catch (RemoteException re) {
Log.w(TAG, "Failed talking with device policy service", re);
}
}
它可以使用如下三种策略,这些策略都不影响已经允许过拒绝的权限
//每次都提醒是否允许
public static final int PERMISSION_POLICY_PROMPT = 0;
//自动允许
public static final int PERMISSION_POLICY_AUTO_GRANT = 1;
//自动拒绝
public static final int PERMISSION_POLICY_AUTO_DENY = 2;
还可以修改指定权限的策略
//Sets the grant state of a runtime permission for a specific application.
public boolean setPermissionGrantState(@NonNull ComponentName admin, String packageName,
String permission, int grantState) {
try {
return mService.setPermissionGrantState(admin, packageName, permission, grantState);
} catch (RemoteException re) {
Log.w(TAG, "Failed talking with device policy service", re);
return false;
}
}
它有如下三种策略可以选择
/**
* Runtime permission state: The user can manage the permission
* through the UI.
*/
public static final int PERMISSION_GRANT_STATE_DEFAULT = 0;
/**
* Runtime permission state: The permission is granted to the app
* and the user cannot manage the permission through the UI.
*/
public static final int PERMISSION_GRANT_STATE_GRANTED = 1;
/**
* Runtime permission state: The permission is denied to the app
* and the user cannot manage the permission through the UI.
*/
public static final int PERMISSION_GRANT_STATE_DENIED = 2;
//From version {@link android.os.Build.VERSION_CODES#M} a profile owner can set:
public void setKeyguardDisabledFeatures(@NonNull ComponentName admin, int which) {
if (mService != null) {
try {
mService.setKeyguardDisabledFeatures(admin, which);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
which可选如下参数
/**
* Disable all keyguard widgets. Has no effect.
*/
public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 1 << 0;
/**
* Disable the camera on secure keyguard screens (e.g. PIN/Pattern/Password)
*/
public static final int KEYGUARD_DISABLE_SECURE_CAMERA = 1 << 1;
/**
* Disable showing all notifications on secure keyguard screens (e.g. PIN/Pattern/Password)
*/
public static final int KEYGUARD_DISABLE_SECURE_NOTIFICATIONS = 1 << 2;
/**
* Only allow redacted notifications on secure keyguard screens (e.g. PIN/Pattern/Password)
*/
public static final int KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS = 1 << 3;
/**
* Ignore trust agent state on secure keyguard screens
* (e.g. PIN/Pattern/Password).
*/
public static final int KEYGUARD_DISABLE_TRUST_AGENTS = 1 << 4;
/**
* Disable fingerprint sensor on keyguard secure screens (e.g. PIN/Pattern/Password).
*/
public static final int KEYGUARD_DISABLE_FINGERPRINT = 1 << 5;
/**
* Disable all current and future keyguard customizations.
*/
public static final int KEYGUARD_DISABLE_FEATURES_ALL = 0x7fffffff;
/**
* Called by a profile or device owner to set the application restrictions for a given target
* application running in the profile.
*/
public void setApplicationRestrictions(@NonNull ComponentName admin, String packageName,
Bundle settings) {
if (mService != null) {
try {
mService.setApplicationRestrictions(admin, packageName, settings);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
//Called by a profile or device owner to set a user restriction specified by the key.
//增加指定的限制
public void addUserRestriction(@NonNull ComponentName admin, String key) {
if (mService != null) {
try {
mService.setUserRestriction(admin, key, true);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
//Called by a profile or device owner to clear a user restriction specified by the key.
//删除指定的限制
public void clearUserRestriction(@NonNull ComponentName admin, String key) {
if (mService != null) {
try {
mService.setUserRestriction(admin, key, false);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
//Only a profile owner can designate the restrictions provider.
public void setRestrictionsProvider(@NonNull ComponentName admin,
@Nullable ComponentName provider) {
if (mService != null) {
try {
mService.setRestrictionsProvider(admin, provider);
} catch (RemoteException re) {
Log.w(TAG, "Failed to set permission provider on device policy service");
}
}
}
//AccessibilityServices可以体现出界面显示上的一切元素变化,可用于辅助盲人使用设备
//Called by a profile or device owner to set the permitted accessibility services.
public boolean setPermittedAccessibilityServices(@NonNull ComponentName admin,
List packageNames) {
if (mService != null) {
try {
return mService.setPermittedAccessibilityServices(admin, packageNames);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
return false;
}
//Called by a profile or device owner to set the permitted input methods services.
public boolean setPermittedInputMethods(@NonNull ComponentName admin, List packageNames) {
if (mService != null) {
try {
return mService.setPermittedInputMethods(admin, packageNames);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
return false;
}
//The calling device admin must be a device or profile owner
public void setScreenCaptureDisabled(@NonNull ComponentName admin, boolean disabled) {
if (mService != null) {
try {
mService.setScreenCaptureDisabled(admin, disabled);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
//Called by a profile owner
public void setBluetoothContactSharingDisabled(@NonNull ComponentName admin, boolean disabled) {
if (mService != null) {
try {
mService.setBluetoothContactSharingDisabled(admin, disabled);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}