开发者

Android - how to receive broadcast intents ACTION_SCREEN_ON/OFF?

    <application>
         <receiver android:name=".MyBroadcastReceiver" android:enabled="true">
                <intent-filter>
                      <action android:name="android.intent.action.ACTION_SCREEN_ON"></action>
                      <action android:name=开发者_如何学C"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?


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.


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...
    }
}


"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;
    }
}


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
            }
        }
    }
}


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
        }
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜