65

Is there a way to detect when a user unlocks the phone? I know about ACTION_SCREEN_ON and ACTION_SCREEN_OFF, but these seem to be fired when the screen switches on/off when pressing the power button, but not actually when the phone gets unlocked when pressing the Menu button...

I am trying to detect the unlock/lock while an activity is running, and I want to resume the activity once unlocked.

Kara
  • 6,115
  • 16
  • 50
  • 57
Chris
  • 651
  • 1
  • 6
  • 4

4 Answers4

65

Here's what to do:

Say you want to detect the unlock event and do something in your activity when the phone is unlocked. Have a Broadcast Receiver for ACTION_SCREEN_ON, ACTION_SCREEN_OFF and ACTION_USER_PRESENT.

onResume of the activity will be called when ACTION_SCREEN_ON is fired. Create a handler and wait for ACTION_USER_PRESENT. When it is fired, implement what you want for your activity.

Credit goes to CommonsWare's answer here: Android -- What happens when device is unlocked?

Community
  • 1
  • 1
Chris
  • 667
  • 4
  • 3
  • 1
    is there anything where i can get callback at c/c++ i.e. at native layer. – CoDe Jun 08 '12 at 15:26
  • 2
    I'd like to point out the `BroadcastReceiver` for these events can only be registered dynamically (by calling `registerReceiver` from within the `Activity`) starting from Android O (API 26). Registering these events in the `AndroidManifest.xml` no longer works hence an application is no longer capable of receiving these events (at least `ACTION_SCREEN_ON` and `ACTION_SCREEN_OFF`) when the app is not running (has been previously killed by Android or force closed by user). – ahasbini Mar 20 '18 at 06:59
  • `ACTION_USER_PRESENT` is not always called. It is not safe to use it. – Michał Dobi Dobrzański Jan 24 '23 at 14:03
28

After struggling with this for a while, I've found that the best way to do this is to register a BroadcastReceiver on the "android.intent.action.USER_PRESENT" action.

"Broadcast Action: Sent when the user is present after device wakes up (e.g when the key-guard is gone)."

To distinguish between cases where the user has turned on phone screen when it wasn't locked, and when they actually unlocked it use the KeyguardManager to check the security settings.

Code example:

Add this to your activity:

registerReceiver(new PhoneUnlockedReceiver(), new IntentFilter("android.intent.action.USER_PRESENT"));

Then use this class:

public class PhoneUnlockedReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        KeyguardManager keyguardManager = (KeyguardManager)context.getSystemService(Context.KEYGUARD_SERVICE);
        if (keyguardManager.isKeyguardSecure()) {
            //phone was unlocked, do stuff here
        }
    }
}       
MrK
  • 652
  • 1
  • 5
  • 17
Doron Manor
  • 576
  • 4
  • 5
  • 1
    Wouldn't you want to check `if(!keyguardManager.isKeyguardLocked())` and `!isDeviceSecure()` on SDK 23+ Devices? – Patrick Mar 18 '17 at 10:10
  • This is a bit wrong as per https://stackoverflow.com/a/30053876/461982 which says you want to check `isDeviceLocked` to verify the actual state, not just if a secure lock has been enabled in Settings. You could also check KeyguardManager's `inKeyguardRestrictedInputMode` for APIs < 22 – Abandoned Cart Jun 12 '17 at 04:14
  • 1
    I tried this but it's not working on Chromebook, is there any other workaround for Chromebook. – Nikhil Apr 02 '21 at 08:46
  • I posted this about six years ago. – Doron Manor Apr 03 '21 at 09:09
8
public class PhoneUnlockedReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)){
            Log.d(TAG, "Phone unlocked");
        }else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)){
            Log.d(TAG, "Phone locked");
        }
    }
}

register receiver by this statement

receiver = new PhoneUnlockedReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_USER_PRESENT);
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        registerReceiver(receiver, filter);
chillworld
  • 4,207
  • 3
  • 23
  • 50
Karan Nagpal
  • 521
  • 1
  • 8
  • 19
  • I am using this cod and its working fine, please check if you have applied any pattern/pin lock or using any third party screen lock app. It may interfere. – Karan Nagpal Jul 03 '17 at 09:44
1

Didn't test it but try the following:

  • Wait for ACTION_SCREEN_ON.
  • (After screen is on,) Wait for ACTION_MAIN with category CATEGORY_HOME (Which launches the home screen) - This is probably what is sent after the phone gets unlocked.

The 1st step is needed to filter out regular HOME key presses.

adamk
  • 45,184
  • 7
  • 50
  • 57
  • But is that going to work on all phones? For eg, on myTouch pressing the Menu button unlocks the phone, some other phones require you to slide across the phone. So is there something that can catch all? – Chris Aug 10 '10 at 05:31
  • I believe so - ACTION_MAIN with category CATEGORY_HOME is definitely called in order to run the home screen (i.e. the launcher). There are many Android phones, however, so I can't be 100% sure. Better give it a try and see if it works for you. – adamk Aug 10 '10 at 05:41
  • I guess I forgot to mention I am running an activity, and while it is running, I want to lock/unlock the screen and resume the activity once unlocked. Waiting for ACTION_MAIN and CATEGORY_HOME just freezes my activity on unlock. – Chris Aug 10 '10 at 06:24
  • Not sure what you mean by freezes. When you lock the phone your activity is paused, and when unlocked it is resumed - so in this specific case (i.e. lock/unlock while you're running), you can probably use these methods to detect what you need. – adamk Aug 10 '10 at 07:09
  • 2
    From Google "ACTION_MAIN with category CATEGORY_HOME -- Launch the home screen." and when you unlock the phone it does not go to the home screen, instead it brings the last used app (resume). – greenoldman Oct 01 '12 at 22:01
  • @adamk but, when the phone opens, another app might be opened. So, this might not work that way – Sambhav Khandelwal May 16 '22 at 03:57