68 votes

Android - comment recevoir les intentions de diffusion 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="android.intent.action.ACTION_SCREEN_OFF"></action>
                </intent-filter>
         </receiver>
...
    </application>

MyBroadcastReceiver est configuré juste pour cracher foo dans les journaux. Cela ne fait rien. Des suggestions ? Dois-je attribuer des autorisations pour que l'intention soit prise en compte ?

70voto

CommonsWare Points 402670

Je pense que ces actions ne peuvent être reçues que par les récepteurs enregistrés dans le code Java (via registerReceiver() ) plutôt que par les récepteurs enregistrés dans le manifeste.

1 votes

OK, je viens de comprendre. Quel est le raisonnement derrière tout ça ?

20 votes

Android ne semble pas prendre en charge les récepteurs enregistrés dans le manifeste pour les cas où ils ne veulent vraiment pas lancer un nouveau processus. Par exemple, vous verrez le même effet avec les actions d'information sur la batterie (par exemple, BATTERY_LOW). Mais au-delà de ça, je n'ai pas beaucoup d'arguments - je ne l'ai pas écrit :-)

2 votes

@CommonsWare Alors comment puis-je enregistrerReceiver() lorsque le bouton Power est pressé ?

32voto

Robert Points 10822

Vous pouvez également utiliser le gestionnaire d'énergie pour détecter le verrouillage de l'écran.

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

2 votes

+1 pour l'approche avec PowerManager Une touche très agréable si quelqu'un ne veut pas utiliser BroadcastReceiver

3 votes

Je voulais juste ajouter que, bien que cette méthode fonctionne parfaitement dans 99 % des cas, elle peut échouer dans certaines circonstances. Dans les appareils qui peuvent allumer et éteindre l'écran très rapidement, comme le Galaxy S4, vous pouvez vérifier que ce comportement échoue en le combinant avec un proximityLock. Si vous déclenchez le verrou pour éteindre et rallumer l'écran rapidement, isScreenOn retournera vrai dans onPause().

0 votes

@iCode4Food Ce que vous avez décrit est juste, mais comment le résoudre ?

31voto

cmcromance Points 668
"android.intent.action.HEADSET_PLUG"
"android.intent.action.ACTION_SCREEN_ON"
"android.intent.action.ACTION_SCREEN_OFF"

Trois d'entre eux ci-dessus, Ils ne peuvent pas s'enregistrer en utilisant Manifest. Le noyau Android leur a ajouté "Intent.FLAG_RECEIVER_REGISTERED_ONLY" (peut-être J'ai vérifié les codes uniquement dans le cas de "HEADSET_PLUG".

Donc, nous devons utiliser le "registre dynamique". Comme ci-dessous...

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

0 votes

+1, bien. La seule chose à noter est que Build.VERSION.SDK n'est pas déprécié.

1 votes

El unregisterReceiver() La partie consacrée au code m'a été très utile. Merci @cmcromance ! ! +1

7voto

box Points 1941

La façon dont je l'ai mis en œuvre est d'enregistrer le récepteur dans mon activité principale dans onCreate(), il suffit de définir le récepteur quelque part au préalable :

    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);

Et ensuite onDestroy() :

    unregisterReceiver(lockScreenReceiver);

Dans le récepteur, vous devez attraper les cas suivants :

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

0voto

Qadir Hussain Points 1766

Voici la version kotlin de @cmcromance (Merci pour votre réponse, n'oubliez pas de noter la réponse originale).

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X