Calling requestDismissKeyguard() twice with a delayed result

1.5k views Asked by At

I'm working on an app that has call capabilities so I need the device to wake up. If the device is locked, I use the following code to unlock it:

keyguardManager.requestDismissKeyguard(this, new KeyguardManager.KeyguardDismissCallback() {

    @Override
    public void onDismissError() {
        super.onDismissError();
        AppLog.d(TAG, "Inside onDismissError()");
    }

    @Override
    public void onDismissSucceeded() {
        super.onDismissSucceeded();
        AppLog.d(TAG, "Inside onDismissSucceeded()");
    }

    @Override
    public void onDismissCancelled() {
        super.onDismissCancelled();
        AppLog.d(TAG, "Inside onDismissCancelled()");
    }
});

On an initial call, the device is unlocking without any issues, but on a second call, there is a delay from when requestDismissKeyguard is called and when the callback is called, so my device stays on with the lock screen open, causing a weird state because the user is expecting an incoming call screen.

See my logs here:

2021-04-21 16:25:39.885: Invoking requestDismissKeyguard()
2021-04-21 16:25:39.994: Inside onDismissCancelled()

2021-04-21 16:25:51.835: Invoking requestDismissKeyguard()
2021-04-21 16:25:55.311: Inside onDismissCancelled()

Notice the difference between the first call (gets canceled within 100ms) and the second call (gets canceled within 4s!!!)

Any ideas? Suggestions?

3

There are 3 answers

0
Furkan Yurdakul On

I assume this code block is in an activity so, I'm not entirely sure why you're trying to request it via keyguard manager (though it looks like it's a proper way after checking the documentation.) Maybe try this:

After calling setContentView you can call getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED) to remove keyguard temporarily for your activity. Finishing the activity should return the keyguard back.

The solution for this follows:


@Override
protected void onCreate(@Nullable Bundle savedInstanceState){
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_layout);

   // Dismiss the keyguard temporarily
   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
      setShowWhenLocked(true);
   } else {
      getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
   }
    
   // Assuming you also want to open the screen and keep it on
   getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
0
Rahul On

You need to add this code:

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED|WindowManager.LayoutParams.FLAG_FULLSCREEN|
                WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.lockscreen);

        startService(new Intent(this,LockService.class).setAction(Intent.ACTION_SCREEN_OFF));
    }

Create LockService with:

@Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {

        if(intent == null || intent.getAction() == null)
            return START_NOT_STICKY;

        String action = intent.getAction();

        if(action.equals(ACTION_SCREEN_OFF))
        {
           KeyguardManager.KeyguardLock k1;
           KeyguardManager km =(KeyguardManager)getSystemService(KEYGUARD_SERVICE);
           k1= km.newKeyguardLock("IN");
           k1.disableKeyguard();  
        }

        return START_NOT_STICKY;
    }

Actually, I don't know why, but k1.disableKeyguard(); works only in Service.

0
Vlad Krasnikov On

Rahul's answer worked for me but there's more:

  1. It seems you don't necessarily need to create a Service. Application context can work as well.
  2. WindowManager.LayoutParams.FLAG_FULLSCREEN flag might be unneccessary and can lead to devices with notches not displaying the status-bar correctly

So:

// Kotlin
override fun onCreate(savedInstanceState: Bundle) {

    window.setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG)
    window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
            WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD)

    val keyguardManager = applicationContext.getSystemService(KEYGUARD_SERVICE) as KeyguardManager
    val keyguardLock = keyguardManager.newKeyguardLock("MY_TAG")
    keyguardLock.disableKeyguard()


    super.onCreate(savedInstanceState);
    setContentView(R.layout.lockscreen);
}