Java – Unable to reset password in Android 7 using Device Policy Manager

Unable to reset password in Android 7 using Device Policy Manager… here is a solution to the problem.

Unable to reset password in Android 7 using Device Policy Manager

I’m having trouble running the app in Android 7 (Nougat).
When a user forgets a password, my app works like a custom recovery. To achieve this, my application requests administrator privileges and observes the number of failed attempts, and if it reaches an X number, a code is generated and sent to the user’s email.

This app works fine on Lollipop and Marshmallow devices, but gets the following error when running in Nougat: java.lang.SecurityException: Cannot call with null password

Email Activity:

private static final String DEFAULT_PASSWORD = "";
 Commented code
DevicePolicyManager devicePolicyManager =
            (DevicePolicyManager) getApplicationContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
devicePolicyManager.resetPassword(DEFAULT_PASSWORD, 0);

Resource @xml/device_admin.xml:

<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-policies>
        <watch-login />
        <reset-password />
    </uses-policies>
</device-admin>

list :

...
<receiver
    android:name="com.example.pin.AdminReceiver"
    android:permission="android.permission.BIND_DEVICE_ADMIN" >
    <intent-filter>

<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
    </intent-filter>
    <meta-data
        android:name="android.app.device_admin"
        android:resource="@xml/device_admin" />
</receiver>
...

Output log:

01-02 06:35:48.383 7354-7354/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.pin, PID: 7354
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.pin/com.example.pin.EmailActivity}: java.lang.SecurityException: Cannot call with null password
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2724)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2789)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1527)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:203)
at android.app.ActivityThread.main(ActivityThread.java:6251)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)
Caused by: java.lang.SecurityException: Cannot call with null password
at android.os.Parcel.readException(Parcel.java:1683)
at android.os.Parcel.readException(Parcel.java:1636)
at android.app.admin.IDevicePolicyManager$Stub$Proxy.resetPassword(IDevicePolicyManager.java:3829)
at android.app.admin.DevicePolicyManager.resetPassword(DevicePolicyManager.java:2242)
at com.example.pin.EmailActivity.onCreate(EmailActivity.java:25)
at android.app.Activity.performCreate(Activity.java:6666)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2677)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2789) 
at android.app.ActivityThread.-wrap12(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1527) 
at android.os.Handler.dispatchMessage(Handler.java:110) 
at android.os.Looper.loop(Looper.java:203) 
at android.app.ActivityThread.main(ActivityThread.java:6251) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)

If you change DEFAULT_PASSWORD to anything different from the empty string, the exception is changed to: java.lang.SecurityException: Admin cannot change current password

Output log:

04-20 22:31:18.228 8880-8880/com.example.pin E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.pin, PID: 8880
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.pin/com.example.pin.EmailActivity}: java.lang.SecurityException: Admin cannot change current password
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2724)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2789)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1527)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:203)
at android.app.ActivityThread.main(ActivityThread.java:6251)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)
Caused by: java.lang.SecurityException: Admin cannot change current password
at android.os.Parcel.readException(Parcel.java:1683)
at android.os.Parcel.readException(Parcel.java:1636)
at android.app.admin.IDevicePolicyManager$Stub$Proxy.resetPassword(IDevicePolicyManager.java:3829)
at android.app.admin.DevicePolicyManager.resetPassword(DevicePolicyManager.java:2242)
at com.example.pin.EmailActivity.onCreate(EmailActivity.java:25)
at android.app.Activity.performCreate(Activity.java:6666)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2677)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2789) 
at android.app.ActivityThread.-wrap12(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1527) 
at android.os.Handler.dispatchMessage(Handler.java:110) 
at android.os.Looper.loop(Looper.java:203) 
at android.app.ActivityThread.main(ActivityThread.java:6251) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924) 

I’ve read from documentation for Android device policy manager, reset password, but didn’t understand what I should do.

Calling with a null or empty password will clear any existing PIN, pattern or password if the current password constraints allow it. Note: This will not work in N and later for managed profiles, or for device admins that are not device owner or profile owner. Once set, the password cannot be changed to null or empty except by these admins.

I did some research and testing, but didn’t find how to make my device management app a device owner or profile owner. Any idea how to solve this problem?

Thanks in advance!

Solution

From Android documentation:
https://developer.android.com/about/versions/nougat/android-7.0-changes.html

“Device administrators’ reset passcode restriction now applies to profile owners. Device administrators can no longer use DevicePolicyManager.resetPassword() to clear passwords or change passwords that have already been set. Device administrators can still set a password, but only if the device doesn’t have a password, PIN, or pattern. ”


I observed the same issue.
When there is no password, resetpassword works.
Failed to clear password.
Changing the password also failed.

Related Problems and Solutions