Medientasten sind Hardwaretasten auf Android-Geräten und anderen Peripheriegeräten, z. B. die Pause-/Wiedergabe-Taste an einem Bluetooth-Headset. Wenn ein Nutzer eine Medienschaltfläche drückt, generiert Android eine KeyEvent
, die einen Schlüsselcode zur Identifizierung der Schaltfläche enthält. Die Schlüsselcodes für Medienschaltflächen-KeyEvents sind Konstanten, die mit KEYCODE_MEDIA
beginnen (z. B. KEYCODE_MEDIA_PLAY
).
Apps sollten Medienschaltflächenereignisse in drei Fällen verarbeiten können – in der folgenden Prioritätsreihenfolge:
- Wenn die UI-Aktivität der App sichtbar ist
- Wenn die UI-Aktivität ausgeblendet ist und die Mediensitzung der App aktiv ist
- Wenn die UI-Aktivität ausgeblendet ist und die Mediensitzung der App inaktiv ist und neu gestartet werden muss
Umgang mit Medienschaltflächen bei einer Aktivität im Vordergrund
Die Vordergrundaktivität empfängt das Schlüsselereignis für die Medienschaltfläche in ihrer onKeyDown()
-Methode. Je nach verwendeter Android-Version gibt es zwei Möglichkeiten, wie das System das Ereignis an einen Mediencontroller weiterleitet:
- Wenn du Android 5.0 (API-Level 21) oder höher verwendest, rufe
FLAG_HANDLES_MEDIA_BUTTONS
MediaBrowserCompat.ConnectionCallback.onConnected
auf. Dadurch wird automatischdispatchMediaButtonEvent()
des Mediencontrollers aufgerufen, der den Schlüsselcode in einen Mediensitzungs-Callback übersetzt. - Vor Android 5.0 (API-Level 21) musst du
onKeyDown()
so ändern, dass das Ereignis selbst verarbeitet wird. Weitere Informationen finden Sie unter Handhabung von Medienschaltflächen in einer aktiven Mediensitzung. Das folgende Code-Snippet zeigt, wie der Schlüsselcode abgefangen und dispatchMediaButtonEvent() aufgerufen wird. Geben Sietrue
zurück, um anzugeben, dass das Ereignis verarbeitet wurde: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); }
Mediensitzung finden
Wenn die Aktivität im Vordergrund das Ereignis nicht verarbeitet, versucht Android, eine Mediensitzung zu finden, die es verarbeiten kann. Auch hier gibt es je nach verwendeter Android-Version zwei Möglichkeiten, nach einer Mediensitzung zu suchen:
Wenn Sie Android 8.0 (API-Level 26) oder höher ausführen, versucht das System, die letzte App mit einer MediaSession zu finden, die Audioinhalte lokal wiedergegeben hat. Wenn die Sitzung noch aktiv ist, sendet Android das Ereignis direkt an sie. Wenn die Sitzung nicht aktiv ist und über einen Mediabutton-Empfänger verfügt, sendet Android das Ereignis an den Empfänger. Dieser startet die Sitzung neu und kann das Ereignis empfangen. Weitere Informationen finden Sie unter Medienschaltflächen zum Neustart einer inaktiven Mediensitzung verwenden. Wenn die Sitzung keinen Medienschaltflächenempfänger hat, verwirft das System das Medienschaltflächenereignis und nichts passiert. Die Logik wird im folgenden Diagramm dargestellt:
Vor Android 8.0 (API-Level 26) versucht das System, das Ereignis an eine aktive Mediensitzung zu senden. Gibt es mehrere aktive Mediensitzungen, versucht Android, statt einer angehaltenen Mediensitzung eine Mediensitzung auszuwählen, die zur Wiedergabe vorbereitet (zwischengespeichert/verbunden), noch abgespielt oder pausiert wird. Weitere Informationen finden Sie unter Medienschaltflächen in einer aktiven Mediensitzung verarbeiten. Wenn keine aktive Sitzung vorhanden ist, versucht Android, das Ereignis an die zuletzt aktive Sitzung zu senden. Weitere Informationen finden Sie unter Medienschaltflächen zum Neustart einer inaktiven Mediensitzung verwenden. Die Logik wird im folgenden Diagramm dargestellt:
Umgang mit Medienschaltflächen in einer aktiven Mediensitzung
Unter Android 5.0 (API-Level 21) und höher sendet Android automatisch Medienschaltflächenereignisse an deine aktive Mediensitzung durch den Aufruf von onMediaButtonEvent()
.
Standardmäßig übersetzt dieser Callback das KeyEvent in die entsprechende Callback-Methode für Mediensitzungen, die dem Schlüsselcode entspricht.
Vor Android 5.0 (API-Level 21) verarbeitet Android Medienschaltflächenereignisse, indem es einen Intent mit der Aktion ACTION_MEDIA_BUTTON
sendet. Deine App muss einen BroadcastReceiver registrieren, um diese Intents abzufangen. Die Klasse MediaButtonReceiver
wurde speziell für diesen Zweck entwickelt. Dabei handelt es sich um eine Convenience-Klasse in der Android-Medienkompatibilitätsbibliothek, die ACTION_MEDIA_BUTTON
verarbeitet und die eingehenden Intents in die entsprechenden MediaSessionCompat.Callback
-Methodenaufrufe umwandelt.
Ein MediaButtonReceiver
ist ein kurzlebiger BroadcastReceiver. Er leitet eingehende Intents an den Dienst weiter, der Ihre Mediensitzung verwaltet. Wenn Sie Medienschaltflächen in Systemen vor Android 5.0 verwenden möchten, müssen Sie MediaButtonReceiver
in Ihr Manifest mit einem MEDIA_BUTTON
-Intent-Filter aufnehmen.:
<receiver android:name="android.support.v4.media.session.MediaButtonReceiver" >
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
BroadcastReceiver
leitet den Intent an Ihren Dienst weiter. Um den Intent zu parsen und den Callback für Ihre Mediensitzung zu generieren, fügen Sie die Methode MediaButtonReceiver.handleIntent()
in die onStartCommand()
Ihres Dienstes ein.
Dadurch wird der Schlüsselcode in die entsprechende Sitzungs-Callback-Methode übersetzt.
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); }
Mit Medientasten eine inaktive Mediensitzung neu starten
Wenn Android die letzte aktive Mediensitzung identifizieren kann, versucht es, die Sitzung neu zu starten. Dazu wird ein ACTION_MEDIA_BUTTON
-Intent an eine Manifest-registrierte Komponente gesendet (z. B. einen Dienst oder BroadcastReceiver
).
So kann die App die Wiedergabe neu starten, während die Benutzeroberfläche nicht sichtbar ist. Das ist bei den meisten Audio-Apps der Fall.
Dieses Verhalten wird automatisch aktiviert, wenn Sie MediaSessionCompat
verwenden. Wenn Sie das MediaSession
-Framework der Android-Framework oder die Support Library 24.0.0 bis 25.1.1 verwenden, müssen Sie setMediaButtonReceiver
aufrufen, damit eine inaktive Mediensitzung über eine Medienschaltfläche neu gestartet wird.
Sie können dieses Verhalten unter Android 5.0 (API-Level 21) und höher deaktivieren, indem Sie einen Null-Medienschaltflächenempfänger festlegen:
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);
Handler für Medienschaltflächen anpassen
Beim Standardverhalten für onMediaButtonEvent()
wird der Schlüsselcode extrahiert und anhand des aktuellen Status der Mediensitzung und der Liste der unterstützten Aktionen ermittelt, welche Methode aufgerufen wird. Beispielsweise ruft KEYCODE_MEDIA_PLAY
onPlay()
auf.
Damit Medienschaltflächen in allen Apps einheitlich funktionieren, sollten Sie das Standardverhalten verwenden und nur für einen bestimmten Zweck davon abweichen. Wenn eine Medienschaltfläche benutzerdefinierte Verarbeitung erfordert, überschreiben Sie die Methode onMediaButtonEvent()
des Callbacks, extrahieren Sie KeyEvent
mit intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT)
, verarbeiten Sie das Ereignis selbst und geben Sie true
zurück.
Zusammenfassung
Damit Medienschaltflächenereignisse in allen Android-Versionen richtig verarbeitet werden, müssen Sie beim Erstellen einer Mediensitzung FLAG_HANDLES_MEDIA_BUTTONS
angeben.
Abhängig von den Android-Versionen, die Sie unterstützen möchten, müssen Sie außerdem die folgenden Anforderungen erfüllen:
Unter Android 5.0 oder höher:
MediaControllerCompat.setMediaController()
über denonConnected()
-Callback der Mediensteuerung aufrufen- Wenn Sie über eine Medienschaltfläche den Neustart einer inaktiven Sitzung zulassen möchten, erstellen Sie dynamisch einen
MediaButtonReceiver
, indem SiesetMediaButtonReceiver()
aufrufen und einPendingIntent
übergeben.
Bei Ausführung in Systemen vor Android 5.0:
- Die
onKeyDown()
der Aktivität für die Verarbeitung von Medienschaltflächen überschreiben MediaButtonReceiver
durch Hinzufügen zum Manifest der App statisch erstellen