'How to reset the password of the lock screen programmatically on Android SDK 26 or higher

In my application I want to change the password of the lock screen programmatically. So I wrote this method to reset the password:

@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);
    }
}

When I call the method I get this error on my device running 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)
...

Before I call this method, I' getting the device admin permissions with this method

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);
}

My policies looks like this

<?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>


Solution 1:[1]

For me this solution worked out:

At first, define admin device permissions

policies.xml

<?xml version="1.0" encoding="utf-8"?> <device-admin> <uses-policies> <reset-password/> </uses-policies> </device-admin>

Then create a class that extend 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);
}

}

Get admin device permission with this function in your 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);
}

Then provision a working profile for your app in the 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();
    }
}

After that set the application package to the working profile

 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);
    }
}

Create a method to generate random password tokens

private byte[] generateRandomPasswordToken() {
    try {
        return SecureRandom.getInstance("SHA1PRNG").generateSeed(32);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
        return null;
    }
}

Finally implement this method to reset the lock screen password with 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);
    }
}

Solution 2:[2]

Please have a look at the documentation, it clearly states there that:

Called by device or profile owner to force set a new device unlock password or a managed profile challenge on current user. This takes effect immediately.

From your code it does not look as if you are a "device or profile owner"; please don't mix that up with "device admin" which your apps seems to be (or is trying to get not sure if it is really successful from your code).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 dudi
Solution 2 BBB