Android - how to receive broadcast intents ACTION_SCREEN_ON/OFF?

AndroidBroadcast

Android Problem Overview


    <application>
         <receiver android:name=".MyBroadcastReceiver" android:enabled="true">
                <intent-filter>
                      <action android:name="android.intent.action.ACTION_SCREEN_ON"></action>
                      <action android:name="android.intent.action.ACTION_SCREEN_OFF"></action>
                </intent-filter>
         </receiver>
...
    </application>

MyBroadcastReceiver is set just to spit foo to the logs. Does nothing. Any suggestions please? Do I need to assign any permissions to catch the intent?

Android Solutions


Solution 1 - Android

I believe that those actions can only be received by receivers registered in Java code (via registerReceiver()) rather than through receivers registered in the manifest.

Solution 2 - Android

Alternatively you can use the power manager to detect screen locking.

@Override
protected void onPause()
{
    super.onPause();

    // If the screen is off then the device has been locked
    PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
	boolean isScreenOn;
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
        isScreenOn = powerManager.isInteractive();
    } else {
        isScreenOn = powerManager.isScreenOn();
    }

    if (!isScreenOn) {

        // The screen has been locked 
        // do stuff...
    }
}

Solution 3 - Android

"android.intent.action.HEADSET_PLUG"
"android.intent.action.ACTION_SCREEN_ON"
"android.intent.action.ACTION_SCREEN_OFF"

Three of them above, They cannot register using Manifest. Android core added "Intent.FLAG_RECEIVER_REGISTERED_ONLY" to them (maybe.. I checked codes only in case of "HEADSET_PLUG".

So, We should use "dynamic register". Like below...

private BroadcastReceiver mPowerKeyReceiver = null;

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

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

			if (strAction.equals(Intent.ACTION_SCREEN_OFF) || strAction.equals(Intent.ACTION_SCREEN_ON)) {
				// > Your playground~!
			}
		}
	};

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

private void unregisterReceiver() {
	int apiLevel = Build.VERSION.SDK_INT;

	if (apiLevel >= 7) {
		try {
			getApplicationContext().unregisterReceiver(mPowerKeyReceiver);
		}
		catch (IllegalArgumentException e) {
			mPowerKeyReceiver = null;
		}
	}
	else {
		getApplicationContext().unregisterReceiver(mPowerKeyReceiver);
		mPowerKeyReceiver = null;
	}
}

Solution 4 - Android

The way I implemented this is by registering the receiver in my main activity in onCreate(), just define the receiver somewhere beforehand:

    lockScreenReceiver = new LockScreenReceiver();
    IntentFilter lockFilter = new IntentFilter();
    lockFilter.addAction(Intent.ACTION_SCREEN_ON);
    lockFilter.addAction(Intent.ACTION_SCREEN_OFF);
    lockFilter.addAction(Intent.ACTION_USER_PRESENT);
    registerReceiver(lockScreenReceiver, lockFilter);

And then onDestroy():

    unregisterReceiver(lockScreenReceiver);

In receiver you must catch the following cases:

public class LockScreenReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        if (intent != null && intent.getAction() != null)
        {
            if (intent.getAction().equals(Intent.ACTION_SCREEN_ON))
            {
                // Screen is on but not unlocked (if any locking mechanism present)
            }
            else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF))
            {
                // Screen is locked
            }
            else if (intent.getAction().equals(Intent.ACTION_USER_PRESENT))
            {
                // Screen is unlocked
            }
        }
    }
}

Solution 5 - Android

Here is the kotlin version of @cmcromance (Thanks for your answer. Please don't forget to upvote the original answer)

private var mPowerKeyReceiver: BroadcastReceiver? = null

    private fun registBroadcastReceiver() {
        val theFilter = IntentFilter()
        /** System Defined Broadcast  */
        theFilter.addAction(Intent.ACTION_SCREEN_ON)
        theFilter.addAction(Intent.ACTION_SCREEN_OFF)

        mPowerKeyReceiver = object : BroadcastReceiver() {
            override fun onReceive(context: Context?, intent: Intent?) {

                Log.e("onReceive", "onReceive called")
                val strAction = intent!!.action

//                if (strAction == Intent.ACTION_SCREEN_OFF || strAction == Intent.ACTION_SCREEN_ON) {
                if (strAction == Intent.ACTION_SCREEN_ON) {
                    // > Your playground~!
                    Log.e("strAction", strAction)
                    val intent = Intent(context, SplashScreenMainAppActivity::class.java)
                    startActivity(intent)
                }

            }
        }

        applicationContext.registerReceiver(mPowerKeyReceiver, theFilter)
    }

    private fun unregisterReceiver() {
        val apiLevel = Build.VERSION.SDK_INT

        if (apiLevel >= 7) {
            try {
                applicationContext.unregisterReceiver(mPowerKeyReceiver)
            } catch (e: IllegalArgumentException) {
                mPowerKeyReceiver = null
            }

        } else {
            applicationContext.unregisterReceiver(mPowerKeyReceiver)
            mPowerKeyReceiver = null
        }
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionohnoesView Question on Stackoverflow
Solution 1 - AndroidCommonsWareView Answer on Stackoverflow
Solution 2 - AndroidRobertView Answer on Stackoverflow
Solution 3 - AndroidcmcromanceView Answer on Stackoverflow
Solution 4 - AndroidboxView Answer on Stackoverflow
Solution 5 - AndroidQadir HussainView Answer on Stackoverflow