69

I've seen a couple of posts on here on how to check if the screen is locked, but none of it has been working for me. It all detects if the actual screen is off or not (not if it's locked).

I have a game in which music plays. When the lock button is pressed, it continues to play. I originally had the music stopping in OnStop, but the application would restart after getting locked, so the music would eventually start up again.

Then, I added KeyboardHidden|orientation to the manifest. This makes it so it doesn't restart the app, but OnStop doesn't seem to get called anymore.

I've tried using PowerManager to see if the screen is on/off, which works, but doesn't help. (I can get the music to stop there, but as soon as you hit the lock button again, the music starts right back up)

Nikos Hidalgo
  • 3,666
  • 9
  • 25
  • 39
Ryan
  • 937
  • 1
  • 10
  • 17
  • [This recent post on the android developers blog](http://android-developers.blogspot.com/2011/11/making-android-games-that-play-nice.html) seems to be somewhat related to your problem. Not sure if it solves this, so I just throw it in here in case you missed it. See if it contains any useful information for you. –  Nov 29 '11 at 20:40
  • Thanks, it is related, however, I'm struggling to figure out how to actually use the onfocuschanged method. – Ryan Nov 29 '11 at 20:51
  • Hey @Ryan. How about letting us know via comment or accept if either of these solutions worked for you. I'm curious about the answer. – Sky Kelsey Apr 10 '13 at 01:10
  • possible duplicate of [How to tell if user is on lock screen from service](http://stackoverflow.com/questions/7044868/how-to-tell-if-user-is-on-lock-screen-from-service) – uthark Sep 20 '13 at 19:41
  • Any app playing music should consider whether it is a good idea to continue once its `View` is not in the foreground any more, regalrdless of whether or not the device is locked, the user choosing a different app to be displayed in the foreground, the system to display a shutdown notice, or whatever. So chances are you're actually asking for the wrong solution. – class stacker Jun 06 '17 at 15:49

9 Answers9

112

There is a better way:

KeyguardManager myKM = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
if( myKM.inKeyguardRestrictedInputMode()) {
 //it is locked
} else {
 //it is not locked
}

No need for broadcastRecievers, permissions or anything similar.

Note: It doesn't work when user has set his/her screen lock to none in settings-->security-->screenlock-->none

Shaul Rosenzweig
  • 1,221
  • 1
  • 9
  • 8
  • Could you please tell me how I get the variable "context"? – FiReTiTi Mar 01 '17 at 18:07
  • @FiReTiTi, you pass it in to the function or you can the code from a class that has a `Context`.... – Sakiboy Mar 10 '17 at 09:49
  • 2
    How do you listen to this on an ongoing basis? In a Timer? – IgorGanapolsky Sep 13 '17 at 17:16
  • 8
    `inKeyguardRestrictedInputMode()` method was deprecated in API level 28. Use `isKeyguardLocked()` instead, which is available since API Level 16. – Christopher Apr 24 '19 at 07:40
  • 1
    inKeyguardRestrictedInputMode is deprecated in API level 28. Use isKeyguardLocked() instead. Please refer https://developer.android.com/reference/kotlin/android/app/KeyguardManager – crmm Jul 30 '19 at 01:26
32

This link might be helpful to others for two things at one place.

Check if the Device is Locked Or Not:

KeyguardManager myKM = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
boolean isPhoneLocked = myKM.inKeyguardRestrictedInputMode();

(Note: above method doesn't work if screenlock is set to none in settings-->security-->screenlock.)

Check If Device is Awake or in Sleep Mode:(for Sdk Version > L Preview < Sdk Version)

PowerManager powerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
isScreenAwake = (Build.VERSION.SDK_INT < 20? powerManager.isScreenOn():powerManager.isInteractive());
android developer
  • 114,585
  • 152
  • 739
  • 1,270
Sagar Shah
  • 4,272
  • 2
  • 25
  • 36
  • Could you please tell me how I get the variable "context"? – FiReTiTi Mar 01 '17 at 18:06
  • 3
    @FiReTiTi, here http://stackoverflow.com/questions/3572463/what-is-context-on-android ... cmon man.... – Sakiboy Mar 10 '17 at 09:51
  • Sorry, I forgot to precise that I work with Appium, so I don't have a direct access to the phone. – FiReTiTi Mar 10 '17 at 18:28
  • 1
    I think that for checking if device is locked, you should use : `isPhoneLocked = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && myKM.isKeyguardLocked) || (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN && myKM.inKeyguardRestrictedInputMode()) ` – android developer Jul 04 '18 at 13:49
  • I guess @androiddeveloper is right. `inKeyguardRestrictedInputMode()` method was deprecated in API level 28. Use `isKeyguardLocked()` instead, which is available since API Level 16. – Christopher Apr 24 '19 at 07:39
  • Isn't there a way to have a callback instead? Do live wallpaper apps really query this all the time? – android developer Jun 06 '22 at 07:49
17

The Above solution is correct but when i get output it gave me an output locked when screen off and and locked when screen on but doesn't gave unlock output when i unlocked device after putting pattern for unlock. So Here is my solution.

private void registerBroadcastReceiver() {

     final IntentFilter theFilter = new IntentFilter();
    /** System Defined Broadcast */
    theFilter.addAction(Intent.ACTION_SCREEN_ON);
    theFilter.addAction(Intent.ACTION_SCREEN_OFF);
    theFilter.addAction(Intent.ACTION_USER_PRESENT);

    BroadcastReceiver screenOnOffReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String strAction = intent.getAction();

            KeyguardManager myKM = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
if(strAction.equals(Intent.ACTION_USER_PRESENT) || strAction.equals(Intent.ACTION_SCREEN_OFF) || strAction.equals(Intent.ACTION_SCREEN_ON)  )
                if( myKM.inKeyguardRestrictedInputMode())
                {
                    System.out.println("Screen off " + "LOCKED");
                } else
                {
                    System.out.println("Screen off " + "UNLOCKED");
                }

        }
    };

    getApplicationContext().registerReceiver(screenOnOffReceiver, theFilter);
}

after that this will give me output like

I/System.out:LOCKED 
when i off the mobile screen
I/System.out:LOCKED
when i on the mobile screen
I/System.out:UNLOCKED
when i unlock the mobile after pattern lock
Love
  • 195
  • 1
  • 3
14

Taken from this link: https://gist.github.com/Jeevuz/4ec01688083670b1f3f92af64e44c112

/**
 * Returns true if the device is locked or screen turned off (in case password not set)
 */
public static boolean isDeviceLocked(Context context) {
    boolean isLocked = false;

    // First we check the locked state
    KeyguardManager keyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
    boolean inKeyguardRestrictedInputMode = keyguardManager.inKeyguardRestrictedInputMode();

    if (inKeyguardRestrictedInputMode) {
        isLocked = true;

    } else {
        // If password is not set in the settings, the inKeyguardRestrictedInputMode() returns false,
        // so we need to check if screen on for this case

        PowerManager powerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
            isLocked = !powerManager.isInteractive();
        } else {
            //noinspection deprecation
            isLocked = !powerManager.isScreenOn();
        }
    }

    Loggi.d(String.format("Now device is %s.", isLocked ? "locked" : "unlocked"));
    return isLocked;
}
Alécio Carvalho
  • 13,481
  • 5
  • 68
  • 74
  • 1
    this solution worked fine for me after i changed: boolean inKeyguardRestrictedInputMode = keyguardManager.inKeyguardRestrictedInputMode(); to boolean inKeyguardRestrictedInputMode = keyguardManager.isKeyguardLocked(); – Elad Dec 28 '18 at 08:34
  • I tried this on Chromebook but it's not working, is there any other Workaround for Chromebook? – Nikhil Apr 02 '21 at 12:17
3

You can use KeyguardManager class to check if the screen is locked or not. Below is the code snippet written in Kotlin.

    val keyguardManager: KeyguardManager = context?.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager

    if (keyguardManager.isDeviceLocked) {
       // device locked logic goes here 
    } else {
       // device unlocked case
    }
karlingen
  • 13,800
  • 5
  • 43
  • 74
Anubhav
  • 1,984
  • 22
  • 17
  • 1
    This soultion works fine, but `isDevicesLocked()` is deprecated, you can use this code in `onStop()` method and instead of using `isDeviceLocked()` use `isKeyguardLocked()` – Ahmed Nezhi Dec 28 '21 at 14:34
2

I would suggest this:

private void registerBroadcastReceiver() {
    final IntentFilter theFilter = new IntentFilter();
    /** System Defined Broadcast */
    theFilter.addAction(Intent.ACTION_SCREEN_ON);
    theFilter.addAction(Intent.ACTION_SCREEN_OFF);

    BroadcastReceiver screenOnOffReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String strAction = intent.getAction();

            KeyguardManager myKM = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);

            if (strAction.equals(Intent.ACTION_SCREEN_OFF) || strAction.equals(Intent.ACTION_SCREEN_ON)) 
            {
                if( myKM.inKeyguardRestrictedInputMode()) 
                {
                    System.out.println("Screen off " + "LOCKED");
                } else 
                {
                    System.out.println("Screen off " + "UNLOCKED");
                }
            }
        }
    };

    getApplicationContext().registerReceiver(screenOnOffReceiver, theFilter);
}

The above answer from @Shaul Rosenzweig combined with the other post available to detect screen on and off status. I tested this solution on Samsung Galaxy S4 Mini and worked well for me.

class Android
  • 762
  • 1
  • 6
  • 17
  • 1
    Unfortunately, this doesn't work when the screen locks X seconds after the screen is turned off. – Sam Jul 15 '16 at 12:15
  • Sorry @Sam it didn't work out for you. But, this does work in my case. – class Android Jul 16 '16 at 08:06
  • 1
    Well, if the phone doesn't lock until 5 seconds *after* the screen locks, your code won't detect the lock screen until the phone's screen is turned on. Not necessarily a big deal. :) – Sam Jul 16 '16 at 10:50
  • Sorry, I meant "5 seconds *after* the screen turns off" – Sam Jul 16 '16 at 11:08
1

The Below code shows if the screen is locked or not.

 private void checkPhoneScreenLocked(){
        KeyguardManager myKM = (KeyguardManager) getApplicationContext().getSystemService(Context.KEYGUARD_SERVICE);
        if( myKM.isKeyguardLocked()) {
            System.out.println("Phone is locked");
        } else {
            System.out.println("Phone is not locked");
        }
    }

enter image description here

DrawBack:-We can check the phone is locked or not.only if the user has selected the any security patters other than none.

vinay shetty
  • 895
  • 1
  • 9
  • 15
0

Luv Kumar's answer works but it only registers when user explicitly locks the screen (by pressing the lock button). Besides that, I want my app to tell when screen goes off (e.g. screen timeout) just did that:

Just added another option to myKM.inKeyguardRestrictedInputMode()

if( myKM.inKeyguardRestrictedInputMode() || (strAction.equals(Intent.ACTION_SCREEN_OFF)) 
psydj1
  • 181
  • 10
0

Use KeyguardManager.isDeviceLocked to detect if the device is currently locked and requires a PIN, pattern or password to unlock.

Ref: https://developer.android.com/reference/android/app/KeyguardManager#isDeviceLocked()

fun isDeviceLocked(context: Context): Boolean {
    return (context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager).isDeviceLocked
}
Harshal Pudale
  • 178
  • 1
  • 2
  • 7