如何在Android SDK 26或更高版本上以编程方式重置锁屏密码
在我的应用程序中,我希望以编程方式更改锁屏的密码。所以我写了这个方法来重置密码:如何在Android SDK 26或更高版本上以编程方式重置锁屏密码,android,securityexception,device-admin,device-policy-manager,Android,Securityexception,Device Admin,Device Policy Manager,在我的应用程序中,我希望以编程方式更改锁屏的密码。所以我写了这个方法来重置密码: @TargetApi(26) private void changePasswordWithToken() { SecureRandom secureRandom = new SecureRandom(); byte[] token = secureRandom.generateSeed(32); DevicePolicyManager devicePolicyManager = (Devi
@TargetApi(26)
private void changePasswordWithToken() {
SecureRandom secureRandom = new SecureRandom();
byte[] token = secureRandom.generateSeed(32);
DevicePolicyManager devicePolicyManager = (DevicePolicyManager) getApplicationContext().getSystemService(
DEVICE_POLICY_SERVICE);
if (devicePolicyManager != null) {
devicePolicyManager.setResetPasswordToken(compName, token);
devicePolicyManager.resetPasswordWithToken(compName, "1234", token, 0);
}
}
当我调用该方法时,我在运行Android 9 SDK 27的设备上遇到此错误
va.lang.SecurityException: Admin ComponentInfo{com.xxx.xxx/com.xxx.xxxx.MyAdmin} does not own the profile
at android.os.Parcel.createException(Parcel.java:1942)
at android.os.Parcel.readException(Parcel.java:1910)
at android.os.Parcel.readException(Parcel.java:1860)
at android.app.admin.IDevicePolicyManager$Stub$Proxy.setResetPasswordToken(IDevicePolicyManager.java:9995)
at android.app.admin.DevicePolicyManager.setResetPasswordToken(DevicePolicyManager.java:3091)
at com.ssaurel.lockdevice.MainActivity.changePasswordWithToken(MainActivity.java:136)
at com.xx.xx.MainActivity.onClick(MainActivity.java:93)
at android.view.View.performClick(View.java:6597)
at android.view.View.performClickInternal(View.java:6574)
...
在调用此方法之前,我将使用此方法获取设备管理员权限
private void provisionDeviceAdmin() {
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(EXTRA_DEVICE_ADMIN, compName);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
"Additional text explaining why we need this permission");
startActivityForResult(intent, RESULT_ENABLE);
}
我的政策是这样的
<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
<uses-policies>
<force-lock />
<reset-password />
</uses-policies>
</device-admin>
请查看文档,文档中明确说明: 由设备或配置文件所有者调用以强制设置新设备解锁 当前用户上的密码或托管配置文件质询。这需要 立即生效
从您的代码来看,它看起来不像您是“设备或配置文件所有者”;请不要将其与“设备管理员”混淆,您的应用程序似乎是“设备管理员”(或试图通过您的代码不确定它是否真的成功)。请查看文档,文档中明确指出: 由设备或配置文件所有者调用以强制设置新设备解锁 当前用户上的密码或托管配置文件质询。这需要 立即生效
从您的代码来看,它看起来不像您是“设备或配置文件所有者”;请不要将其与“设备管理员”混淆,您的应用程序似乎是“设备管理员”(或试图通过您的代码确定它是否真的成功)。对于我来说,此解决方案解决了: 首先,定义管理设备权限 policies.xml
然后创建一个扩展DeviceAdminReceiver
public class MyAdmin extends DeviceAdminReceiver {
@Override
public void onEnabled(Context context, Intent intent) {
Toast.makeText(context, "Device Admin : enabled", Toast.LENGTH_SHORT).show();
}
@Override
public void onDisabled(Context context, Intent intent) {
Toast.makeText(context, "Device Admin : disabled", Toast.LENGTH_SHORT).show();
}
/**
* Generates a {@link ComponentName} that is used throughout the app.
* @return a {@link ComponentName}
*/
public static ComponentName getComponentName(Context context) {
return new ComponentName(context.getApplicationContext(), MyAdmin.class);
}
}
在MainActivity
private void provisionDeviceAdmin() {
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(EXTRA_DEVICE_ADMIN, MyAdmin.getComponentName(this));
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
"Additional text explaining why we need this permission");
startActivityForResult(intent, RESULT_ENABLE);
}
private void provisionManagedProfile() {
Intent intent = new Intent(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE);
// Use a different intent extra below M to configure the admin component.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
//noinspection deprecation
intent.putExtra(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME,
MyAdmin.getComponentName(this));
} else {
final ComponentName component = new ComponentName(this,
MyAdmin.class.getName());
intent.putExtra(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
component);
}
if (intent.resolveActivity(this.getPackageManager()) != null) {
startActivityForResult(intent, REQUEST_PROVISION_MANAGED_PROFILE);
this.finish();
} else {
Toast.makeText(this, "Device provisioning is not enabled. Stopping.",
Toast.LENGTH_SHORT).show();
}
}
然后在main活动
private void provisionDeviceAdmin() {
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(EXTRA_DEVICE_ADMIN, MyAdmin.getComponentName(this));
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
"Additional text explaining why we need this permission");
startActivityForResult(intent, RESULT_ENABLE);
}
private void provisionManagedProfile() {
Intent intent = new Intent(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE);
// Use a different intent extra below M to configure the admin component.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
//noinspection deprecation
intent.putExtra(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME,
MyAdmin.getComponentName(this));
} else {
final ComponentName component = new ComponentName(this,
MyAdmin.class.getName());
intent.putExtra(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
component);
}
if (intent.resolveActivity(this.getPackageManager()) != null) {
startActivityForResult(intent, REQUEST_PROVISION_MANAGED_PROFILE);
this.finish();
} else {
Toast.makeText(this, "Device provisioning is not enabled. Stopping.",
Toast.LENGTH_SHORT).show();
}
}
最后实现此方法,用令牌重置锁屏密码
@TargetApi(26)
private void changePasswordWithToken() {
byte[] token = generateRandomPasswordToken();
DevicePolicyManager devicePolicyManager = (DevicePolicyManager) getApplicationContext().getSystemService(
DEVICE_POLICY_SERVICE);
KeyguardManager keyguardManager = (KeyguardManager) this.getSystemService(KEYGUARD_SERVICE);
keyguardManager.createConfirmDeviceCredentialIntent(null, null);
if (devicePolicyManager != null) {
devicePolicyManager.setResetPasswordToken(MyAdmin.getComponentName(this), token);
devicePolicyManager.resetPasswordWithToken(MyAdmin.getComponentName(this), "1234", token, 0);
}
}
对我来说,这个解决方案奏效了: 首先,定义管理设备权限 policies.xml
然后创建一个扩展DeviceAdminReceiver
public class MyAdmin extends DeviceAdminReceiver {
@Override
public void onEnabled(Context context, Intent intent) {
Toast.makeText(context, "Device Admin : enabled", Toast.LENGTH_SHORT).show();
}
@Override
public void onDisabled(Context context, Intent intent) {
Toast.makeText(context, "Device Admin : disabled", Toast.LENGTH_SHORT).show();
}
/**
* Generates a {@link ComponentName} that is used throughout the app.
* @return a {@link ComponentName}
*/
public static ComponentName getComponentName(Context context) {
return new ComponentName(context.getApplicationContext(), MyAdmin.class);
}
}
在MainActivity
private void provisionDeviceAdmin() {
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(EXTRA_DEVICE_ADMIN, MyAdmin.getComponentName(this));
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
"Additional text explaining why we need this permission");
startActivityForResult(intent, RESULT_ENABLE);
}
private void provisionManagedProfile() {
Intent intent = new Intent(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE);
// Use a different intent extra below M to configure the admin component.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
//noinspection deprecation
intent.putExtra(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME,
MyAdmin.getComponentName(this));
} else {
final ComponentName component = new ComponentName(this,
MyAdmin.class.getName());
intent.putExtra(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
component);
}
if (intent.resolveActivity(this.getPackageManager()) != null) {
startActivityForResult(intent, REQUEST_PROVISION_MANAGED_PROFILE);
this.finish();
} else {
Toast.makeText(this, "Device provisioning is not enabled. Stopping.",
Toast.LENGTH_SHORT).show();
}
}
然后在main活动
private void provisionDeviceAdmin() {
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(EXTRA_DEVICE_ADMIN, MyAdmin.getComponentName(this));
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
"Additional text explaining why we need this permission");
startActivityForResult(intent, RESULT_ENABLE);
}
private void provisionManagedProfile() {
Intent intent = new Intent(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE);
// Use a different intent extra below M to configure the admin component.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
//noinspection deprecation
intent.putExtra(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME,
MyAdmin.getComponentName(this));
} else {
final ComponentName component = new ComponentName(this,
MyAdmin.class.getName());
intent.putExtra(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
component);
}
if (intent.resolveActivity(this.getPackageManager()) != null) {
startActivityForResult(intent, REQUEST_PROVISION_MANAGED_PROFILE);
this.finish();
} else {
Toast.makeText(this, "Device provisioning is not enabled. Stopping.",
Toast.LENGTH_SHORT).show();
}
}
最后实现此方法,用令牌重置锁屏密码
@TargetApi(26)
private void changePasswordWithToken() {
byte[] token = generateRandomPasswordToken();
DevicePolicyManager devicePolicyManager = (DevicePolicyManager) getApplicationContext().getSystemService(
DEVICE_POLICY_SERVICE);
KeyguardManager keyguardManager = (KeyguardManager) this.getSystemService(KEYGUARD_SERVICE);
keyguardManager.createConfirmDeviceCredentialIntent(null, null);
if (devicePolicyManager != null) {
devicePolicyManager.setResetPasswordToken(MyAdmin.getComponentName(this), token);
devicePolicyManager.resetPasswordWithToken(MyAdmin.getComponentName(this), "1234", token, 0);
}
}