Réaction aux boutons multimédias

Les boutons multimédias sont des boutons physiques présents sur les appareils Android et d'autres périphériques, comme le bouton Pause/Lecture d'un casque Bluetooth. Lorsqu'un utilisateur appuie sur un bouton multimédia, Android génère un KeyEvent, qui contient un code clavier qui identifie le bouton. Les codes clés des KeyEvents de boutons multimédias sont des constantes commençant par KEYCODE_MEDIA (par exemple, KEYCODE_MEDIA_PLAY).

Les applications doivent pouvoir gérer les événements de bouton multimédia dans trois cas, dans cet ordre de priorité:

  • Lorsque l'activité de l'interface utilisateur de l'application est visible
  • Lorsque l'activité de l'interface utilisateur est masquée et que la session multimédia de l'application est active
  • Lorsque l'activité de l'interface utilisateur est masquée et que la session multimédia de l'application est inactive et doit être redémarrée

Gérer les boutons multimédias dans une activité de premier plan

L'activité de premier plan reçoit l'événement de touche du bouton multimédia dans son onKeyDown(). . Selon la version d'Android en cours d'exécution, le système achemine l'événement de deux façons un contrôleur multimédia:

  • Si vous utilisez Android 5.0 (niveau d'API 21) ou une version ultérieure, appelez FLAG_HANDLES_MEDIA_BUTTONS MediaBrowserCompat.ConnectionCallback.onConnected Cela permettra appelle automatiquement l'API dispatchMediaButtonEvent(), qui traduit le code de la touche en rappel de session multimédia.
  • Pour les versions antérieures à Android 5.0 (niveau d'API 21), vous devez modifier onKeyDown() pour gérer l'événement vous-même. Pour en savoir plus, consultez Gérer les boutons multimédias dans une session multimédia active. L'extrait de code suivant montre comment intercepter code de touche et appeler patchMediaButtonEvent(). Assurez-vous de renvoyer true à indiquer que l'événement a été géré:

    Kotlin

        fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                return super.onKeyDown(keyCode, event)
            }
            when (keyCode) {
                KeyEvent.KEYCODE_MEDIA_PLAY -> {
                    yourMediaController.dispatchMediaButtonEvent(event)
                    return true
                }
            }
            return super.onKeyDown(keyCode, event)
        }
        

    Java

        @Override
        boolean onKeyDown(int keyCode, KeyEvent event) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                  return super.onKeyDown(keyCode, event);
                }
                switch (keyCode) {
                  case KeyEvent.KEYCODE_MEDIA_PLAY:
                          yourMediaController.dispatchMediaButtonEvent(event);
                          return true;
                }
                return super.onKeyDown(keyCode, event);
        }
        

Trouver une session multimédia

Si l'activité au premier plan ne gère pas l'événement, Android tente de trouver un et la session multimédia qui peut la gérer. Là encore, selon la version en cours d'exécution Android, il existe deux façons de rechercher une session multimédia:

  • Si vous utilisez Android 8.0 (niveau d'API 26) ou une version ultérieure, le système tente de trouver la dernière application dotée d'une MediaSession qui a lu du contenu audio en local. Si la session est toujours actif, Android lui envoie directement l'événement. Sinon, si le la session n'est pas active et qu'elle dispose d'un récepteur Mediabutton, Android envoie l'événement au récepteur, qui redémarrera la session et pourra recevoir l'événement. Pour en savoir plus, consultez Utiliser des boutons multimédias pour redémarrer une session multimédia inactive. Si la session n'a pas de bouton multimédia, le système le supprime. et il ne se passe rien. La logique est illustrée dans l'exemple suivant : diagramme:

  • Sur les versions antérieures à Android 8.0 (niveau d'API 26), le système tente d'envoyer l'événement à session multimédia active. S'il existe plusieurs sessions multimédias actives, Android tente choisir une session multimédia en cours de préparation à la lecture (mise en mémoire tampon/connexion), en cours de lecture ou en pause, plutôt qu'une lecture arrêtée. (Voir Gérer les boutons multimédias dans une session multimédia active pour en savoir plus.) S'il n'y a pas de , Android tente d'envoyer l'événement à la dernière session active. Pour en savoir plus, consultez Utiliser des boutons multimédias pour redémarrer une session multimédia inactive. La logique est illustrée dans le schéma suivant:

Gérer les boutons multimédias dans une session multimédia active

Sur Android 5.0 (niveau d'API 21) ou version ultérieure, Android envoie automatiquement les événements du bouton multimédia à votre session multimédia active en appelant onMediaButtonEvent() Par défaut, ce rappel traduit l'événement KeyEvent dans la méthode de rappel de session multimédia appropriée qui correspond au code de touche.

Avant Android 5.0 (niveau d'API 21), Android gère les événements du bouton multimédia en diffusant un intent. avec l'action ACTION_MEDIA_BUTTON. Votre application doit enregistrer un BroadcastReceiver pour intercepter ces intents. La MediaButtonReceiver a été spécialement conçu pour à cette fin. Il s'agit d'une classe pratique dans Sur Android bibliothèque Media-Compat qui gère ACTION_MEDIA_BUTTON et traduit les intents entrants en les appels de méthode MediaSessionCompat.Callback appropriés.

Un MediaButtonReceiver est un BroadcastReceiver de courte durée. Il transfère les appels entrants au service qui gère votre session multimédia. Si vous souhaitez utiliser boutons multimédias sur les systèmes antérieurs à Android 5.0, vous devez inclure MediaButtonReceiver dans votre fichier manifeste avec un filtre d'intent MEDIA_BUTTON:

<receiver android:name="android.support.v4.media.session.MediaButtonReceiver" >
   <intent-filter>
     <action android:name="android.intent.action.MEDIA_BUTTON" />
   </intent-filter>
 </receiver>

BroadcastReceiver transmet l'intent à votre service. Pour analyser l'intent puis générez le rappel de votre session multimédia, incluez la méthode MediaButtonReceiver.handleIntent() dans le fichier onStartCommand() de votre service. Le code de touche est alors traduit dans la méthode de rappel de session appropriée.

Kotlin

private val mediaSessionCompat: MediaSessionCompat = ...

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    MediaButtonReceiver.handleIntent(mediaSessionCompat, intent)
    return super.onStartCommand(intent, flags, startId)
}

Java

private MediaSessionCompat mediaSessionCompat = ...;

 public int onStartCommand(Intent intent, int flags, int startId) {
   MediaButtonReceiver.handleIntent(mediaSessionCompat, intent);
   return super.onStartCommand(intent, flags, startId);
 }

Utilisation de boutons multimédias pour redémarrer une session multimédia inactive

Si Android peut identifier la dernière session multimédia active, il tente de la redémarrer en envoyant un intent ACTION_MEDIA_BUTTON à un composant enregistré dans le fichier manifeste (comme un service ou BroadcastReceiver).

Cela permet à votre application de redémarrer la lecture lorsque son interface utilisateur n'est pas visible, ce qui est le cas pour la plupart des applications audio.

Ce comportement est automatiquement activé lorsque vous utilisez MediaSessionCompat. Si vous utilisez MediaSession du framework Android ou la bibliothèque Support 24.0.0 à 25.1.1, vous devez appeler setMediaButtonReceiver pour permettre à un bouton multimédia de redémarrer une session multimédia inactive.

Vous pouvez désactiver ce comportement sous Android 5.0 (niveau d'API 21) ou version ultérieure en procédant comme suit : définir un récepteur de bouton multimédia "null" :

Kotlin

// Create a MediaSessionCompat
mediaSession = MediaSessionCompat(context, LOG_TAG)
mediaSession.setMediaButtonReceiver(null)

Java

// Create a MediaSessionCompat
mediaSession = new MediaSessionCompat(context, LOG_TAG);
mediaSession.setMediaButtonReceiver(null);

Personnaliser les gestionnaires de boutons multimédias

Le comportement par défaut de onMediaButtonEvent() extrait le code de clé et utilise l'état actuel de la session multimédia ainsi que la liste des actions compatibles pour déterminer la méthode à appeler. Par exemple, KEYCODE_MEDIA_PLAY appelle onPlay().

Pour proposer une expérience cohérente pour les boutons multimédias dans toutes les applications, vous devez utiliser le comportement par défaut et ne dévier que dans un but spécifique. Si un bouton multimédia nécessite une gestion personnalisée, remplacez le paramètre onMediaButtonEvent() , extrayez KeyEvent à l'aide de intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT), gérer l'événement vous-même et renvoyer true.

Résumé

Pour gérer correctement les événements de bouton multimédia dans toutes les versions d'Android, vous devez spécifier FLAG_HANDLES_MEDIA_BUTTONS lorsque vous créez une session multimédia.

De plus, selon les versions d'Android que vous prévoyez de prendre en charge, vous devez également remplir les conditions suivantes:

Sous Android 5.0 ou version ultérieure:

  • Appeler MediaControllerCompat.setMediaController() à partir du rappel onConnected() de la commande multimédia
  • Pour autoriser un bouton multimédia à redémarrer une session inactive, créez un MediaButtonReceiver de manière dynamique en appelant setMediaButtonReceiver() et en lui transmettant un PendingIntent

Sur des systèmes antérieurs à Android 5.0:

  • Remplacer le onKeyDown() de l'activité pour gérer les boutons multimédias
  • Créer un MediaButtonReceiver de manière statique en l'ajoutant au fichier manifeste de l'application