androidnotificationslockscreenkeyguard

Disabled Keyguard Lock re-enables itself after clicking on a notification


In my application I disable the keyguard lock (i.e.Remove Lockscreen) using the code below and it works fine until I click on any notification in the notification bar. If I click on a notification the lock screen is automatically re-enabled. Any help is appreciated.

private void remove_lockscreen() {
    final CheckBoxPreference lock = (CheckBoxPreference) findPreference("remove_lockscreen");
    KeyguardManager km = (KeyguardManager)getSystemService(KEYGUARD_SERVICE);
    KeyguardLock kl = km.newKeyguardLock("keyguard_lock");
    if (lock.isChecked()) {
        prefEdit("remove_lockscreen", 1);
        Toast.makeText(getBaseContext(), "Lockscreen will not be shown", Toast.LENGTH_SHORT).show();
        kl.disableKeyguard();
    }
    else if (!lock.isChecked()) {
        prefEdit("remove_lockscreen", 0);
        Toast.makeText(getBaseContext(), "Lockscreen will be shown", Toast.LENGTH_SHORT).show();
        kl.reenableKeyguard();
        android.os.Process.killProcess(android.os.Process.myPid());
    }
}

Solution

  • I've noticed the same issue for some time. It only occurs on Honeycomb (Android 3.0) and up. After a great deal of experimentation and hair-pulling, I seem to have found a solution that works for me. It's not clear exactly what's going on or why, but here's what I've figured out.

    It seems that on Android 3.0+, after the keyguard is disabled, when a notification is pressed, the old KeyguardLock expires, but thankfully the ACTION_USER_PRESENT Broadcast is fired at that point, so we have a chance to correct the issue.

    One point that's not at all obvious from the documentation is that it seems to be necessary to reenable the old KeyguardLock before getting a new one and disabling it again. Another "gotcha" I discovered is that disabling through the new KeyguardLock immediately after reenabling through the old one produces only intermittent success. I resolved this by waiting 300ms before disabling.

    Here's a slightly simplified version of my code; it should be easy to adapt to your app:

    private KeyguardLock kl;
    private KeyguardManager km;
    
    private final Handler mHandler = new Handler();
    
    private final Runnable runDisableKeyguard = new Runnable() {
        public void run() {
            kl = km.newKeyguardLock(getPackageName());
            kl.disableKeyguard();
        }
    };
    
    private void setEnablednessOfKeyguard(boolean enabled) {
        if (enabled) {
            if (kl != null) {
                unregisterReceiver(mUserPresentReceiver);
                mHandler.removeCallbacks(runDisableKeyguard);
                kl.reenableKeyguard();
                kl = null;
            }
        } else {
            if (km.inKeyguardRestrictedInputMode()) {
                registerReceiver(mUserPresentReceiver, userPresent);
            } else {
                if (kl != null)
                    kl.reenableKeyguard();
                else
                    registerReceiver(mUserPresentReceiver, userPresent);
    
                mHandler.postDelayed(runDisableKeyguard,  300);
            }
        }
    }
    
    private final BroadcastReceiver mUserPresentReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())){
                if (sp_store.getBoolean(KEY_DISABLE_LOCKING, false))
                    setEnablednessOfKeyguard(false);
            }
        }
    };