如何在 Android SDK 26 或更高版本上以编程方式重置锁屏密码
Posted
技术标签:
【中文标题】如何在 Android SDK 26 或更高版本上以编程方式重置锁屏密码【英文标题】:How to reset the password of the lock screen programmatically on Android SDK 26 or higher 【发布时间】:2020-01-03 13:02:12 【问题描述】:在我的应用程序中,我想以编程方式更改锁定屏幕的密码。所以我写了这个方法来重置密码:
@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 ComponentInfocom.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>
【问题讨论】:
【参考方案1】:请查看文档,其中明确指出:
由设备或个人资料所有者调用以强制设置新设备解锁 当前用户的密码或托管配置文件质询。这需要 立即生效。
从您的代码看来,您不是“设备或个人资料所有者”;请不要将其与您的应用看起来的“设备管理员”混为一谈(或试图从您的代码中不确定它是否真的成功)。
【讨论】:
【参考方案2】:对我来说,这个解决方案很有效:
首先,定义管理员设备权限
policies.xml
<?xml version="1.0" encoding="utf-8"?>
<device-admin>
<uses-policies>
<reset-password/>
</uses-policies>
</device-admin>
然后创建一个扩展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);
然后在MainActivity
中为您的应用配置工作配置文件
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();
然后将应用程序包设置为工作配置文件
private void setAppEnabled(String packageName, boolean enabled)
PackageManager packageManager = getPackageManager();
DevicePolicyManager devicePolicyManager =
(DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
try
int packageFlags;
if(Build.VERSION.SDK_INT < 24)
//noinspection deprecation
packageFlags = PackageManager.GET_UNINSTALLED_PACKAGES;
else
packageFlags = PackageManager.MATCH_UNINSTALLED_PACKAGES;
ApplicationInfo applicationInfo = packageManager.getApplicationInfo(packageName,
packageFlags);
// Here, we check the ApplicationInfo of the target app, and see if the flags have
// ApplicationInfo.FLAG_INSTALLED turned on using bitwise operation.
if (0 == (applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED))
// If the app is not installed in this profile, we can enable it by
// DPM.enableSystemApp
if (enabled)
devicePolicyManager.enableSystemApp(MyAdmin.getComponentName(this), packageName);
else
// But we cannot disable the app since it is already disabled
Log.e("TAG", "Cannot disable this app: " + packageName);
return;
else
// If the app is already installed, we can enable or disable it by
// DPM.setApplicationHidden
devicePolicyManager.setApplicationHidden(
MyAdmin.getComponentName(this), packageName, !enabled);
Toast.makeText(this, enabled ? "Enabled" : "Disabled",
Toast.LENGTH_SHORT).show();
catch (PackageManager.NameNotFoundException e)
Log.e("TAG", "The app cannot be found: " + packageName, e);
创建一个生成随机密码令牌的方法
private byte[] generateRandomPasswordToken()
try
return SecureRandom.getInstance("SHA1PRNG").generateSeed(32);
catch (NoSuchAlgorithmException e)
e.printStackTrace();
return null;
终于实现了这个用token重置锁屏密码的方法
@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);
【讨论】:
以上是关于如何在 Android SDK 26 或更高版本上以编程方式重置锁屏密码的主要内容,如果未能解决你的问题,请参考以下文章
在Android 1.0或更高版本中使Android项目Gradle兼容
此 Android SDK 需要 ADT 版本 23.0.0 或更高版本。当前版本是 22.6。请更新 ADT 到最新版本? [复制]
PhoneGap iOS 提交错误:ITMS-90807:无效授权 - 如何使用 SDK 13 或更高版本进行构建?
如何查看我的 Xamarin.Forms 应用程序是不是在 Visual Studio 中的 Android 6(或更高版本)上运行或/和可运行?