Przyciski multimediów to przyciski sprzętowe dostępne na urządzeniach z Androidem i innych urządzeniach peryferyjnych, np. przycisk wstrzymania/odtwarzania w zestawie słuchawkowym Bluetooth. Gdy użytkownik kliknie przycisk multimediów, Android generuje kod KeyEvent
zawierający kod klucza, który identyfikuje ten przycisk. Kody kluczy zdarzeń KeyEvents przycisku mediów są stałymi zaczynającymi się od KEYCODE_MEDIA
(np. KEYCODE_MEDIA_PLAY
).
Aplikacje powinny obsługiwać zdarzenia przycisków multimediów w 3 przypadkach, w tej kolejności według priorytetu:
- Gdy aktywność w interfejsie użytkownika jest widoczna
- Gdy aktywność w interfejsie jest ukryta, a sesja multimediów w aplikacji jest aktywna
- Gdy aktywność w interfejsie jest ukryta, a sesja multimediów w aplikacji jest nieaktywna i wymaga ponownego uruchomienia
Obsługa przycisków multimediów w aktywności na pierwszym planie
Aktywność na pierwszym planie odbiera w metodzie onKeyDown()
zdarzenie klucza multimediów. W zależności od używanej wersji Androida system może kierować zdarzenie do kontrolera multimediów na 2 sposoby:
- Jeśli używasz Androida 5.0 (poziom interfejsu API 21) lub nowszego, wywołaj metodę
FLAG_HANDLES_MEDIA_BUTTONS
MediaBrowserCompat.ConnectionCallback.onConnected
. Spowoduje to automatyczne wywołanie funkcjidispatchMediaButtonEvent()
kontrolera multimediów, która przekształci kod klucza na wywołanie zwrotne sesji multimediów. - W wersjach starszych niż 5.0 (poziom interfejsu API 21) musisz zmodyfikować
onKeyDown()
, aby samodzielnie obsługiwał zdarzenie. (więcej informacji znajdziesz w sekcji Obsługa przycisków multimediów w aktywnej sesji multimediów). Poniższy fragment kodu pokazuje, jak przechwycić kod klucza i wywołać metodę dispatchMediaButtonEvent(). Pamiętaj, aby zwrócićtrue
, aby wskazać, że zdarzenie zostało przetworzone: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); }
Szukam sesji multimediów
Jeśli aktywność na pierwszym planie nie obsługuje danego zdarzenia, Android spróbuje znaleźć sesję multimediów, która to umożliwia. W zależności od wersji Androida są dwa sposoby wyszukiwania sesji multimediów:
Jeśli używasz Androida 8.0 (poziom interfejsu API 26) lub nowszego, system próbuje znaleźć ostatnią aplikację z funkcją MediaSession, która odtwarzała dźwięk lokalnie. Jeśli sesja jest nadal aktywna, Android wysyła zdarzenie bezpośrednio do niej. W przeciwnym razie, jeśli sesja jest nieaktywna i ma odbiornik mediabutton, Android wysyła zdarzenie do odbiornika, co spowoduje ponowne uruchomienie sesji i jej odebranie. (Szczegółowe informacje znajdziesz w artykule Ponowne uruchamianie nieaktywnej sesji multimediów przy użyciu przycisków multimediów). Jeśli sesja nie ma odbiornika przycisku multimediów, system odrzuca zdarzenie przycisku multimediów i nic się nie dzieje. Logika ta jest przedstawiona na tym diagramie:
W wersjach starszych niż 8.0 (poziom interfejsu API 26) system próbuje wysłać zdarzenie do aktywnej sesji multimediów. Jeśli jest wiele aktywnych sesji multimediów, Android próbuje wybrać taką, która jest przygotowywana do odtwarzania (buforowania/łączenia), odtwarzana lub wstrzymana, a nie zatrzymana. Więcej informacji znajdziesz w sekcji Obsługa przycisków multimediów w aktywnej sesji multimediów. Jeśli nie ma aktywnej sesji, Android próbuje wysłać zdarzenie do ostatnio aktywnej sesji. (Szczegółowe informacje znajdziesz w artykule Ponowne uruchamianie nieaktywnej sesji multimediów przy użyciu przycisków multimediów). Logika ta została przedstawiona na tym diagramie:
Obsługa przycisków multimediów w aktywnej sesji multimediów
Na Androidzie 5.0 (poziom interfejsu API 21) i nowszych Android automatycznie wysyła zdarzenia przycisków multimediów do aktywnej sesji multimediów, wywołując onMediaButtonEvent()
.
Domyślnie to wywołanie zwrotne przekształca zdarzenie KeyEvent na odpowiednią metodę wywołania zwrotnego sesji multimedialnej, która pasuje do kodu klucza.
Przed Androidem 5.0 (poziom interfejsu API 21) Android obsługuje zdarzenia przycisków multimediów, transmitując intencję z działaniem ACTION_MEDIA_BUTTON
. Aby przechwycić te intencje, aplikacja musi zarejestrować obiekt BroadcastOdbieranier. Zajęcia MediaButtonReceiver
zostały zaprojektowane właśnie w tym celu. Jest to klasa wygodna w bibliotece media-compat Androida, która obsługuje ACTION_MEDIA_BUTTON
i tłumaczy przychodzące intencje na odpowiednie wywołania metody MediaSessionCompat.Callback
.
MediaButtonReceiver
to działający przez krótki czas Broadcastodbiornik. Przekazuje ona zamiary przychodzące do usługi, która zarządza Twoją sesją multimediów. Jeśli chcesz używać przycisków multimediów w systemach starszych niż Android 5.0, musisz uwzględnić w pliku manifestu parametr MediaButtonReceiver
z filtrem intencji 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
przekazuje intencję do Twojej usługi. Aby przeanalizować intencję i wygenerować wywołanie zwrotne do sesji multimediów, umieść metodę MediaButtonReceiver.handleIntent()
w pliku onStartCommand()
usługi.
W ten sposób kod klucza zostanie przekształcony w odpowiednią metodę wywołania zwrotnego sesji.
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); }
Używanie przycisków multimediów do ponownego uruchamiania nieaktywnej sesji multimediów
Jeśli Android jest w stanie zidentyfikować ostatnią aktywną sesję multimediów, próbuje zrestartować sesję, wysyłając intencję ACTION_MEDIA_BUTTON
do komponentu zarejestrowanego w pliku manifestu (np. usługi lub BroadcastReceiver
).
Dzięki temu aplikacja może ponownie uruchomić odtwarzanie, gdy jej interfejs nie jest widoczny. Tak dzieje się w przypadku większości aplikacji audio.
To zachowanie jest automatycznie włączone, gdy używasz MediaSessionCompat
. Jeśli używasz pakietu MediaSession
platformy Android lub biblioteki pomocy technicznej od 24.0.0 do 25.1.1, musisz wywołać metodę setMediaButtonReceiver
, aby przycisk multimediów mógł ponownie uruchomić nieaktywne sesje multimediów.
Możesz wyłączyć to działanie w Androidzie 5.0 (poziom interfejsu API 21) i nowszych, ustawiając odbiornik przycisku multimedialnego o wartości 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);
Dostosowywanie modułów obsługi przycisków multimediów
Domyślne działanie onMediaButtonEvent()
wyodrębnia kod klucza i określa, którą metodę wywołać, na podstawie bieżącego stanu sesji multimediów i listy obsługiwanych działań. Na przykład KEYCODE_MEDIA_PLAY
wywołuje metodę onPlay()
.
Aby przyciski multimediów działały tak samo we wszystkich aplikacjach, używaj działania domyślnego i zmieniaj ustawienia tylko w konkretnym celu. Jeśli przycisk multimediów wymaga niestandardowej obsługi, zastąp metodę onMediaButtonEvent()
wywołania zwrotnego, wyodrębnij parametr KeyEvent
za pomocą intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT)
, przygotuj zdarzenie samodzielnie i zwróć true
.
Podsumowanie
Aby prawidłowo obsługiwać zdarzenia przycisków multimediów we wszystkich wersjach Androida, podczas tworzenia sesji multimediów musisz określić FLAG_HANDLES_MEDIA_BUTTONS
.
Dodatkowo w zależności od wersji Androida, które mają być obsługiwane, musisz też spełniać te wymagania:
Jeśli korzystasz z Androida w wersji 5.0 lub nowszej:
- Wywołaj
MediaControllerCompat.setMediaController()
z kontrolera multimediów przez wywołanie zwrotneonConnected()
- Aby umożliwić przyciskowi multimediów ponowne uruchomienie nieaktywnej sesji, utwórz dynamicznie obiekt
MediaButtonReceiver
, wywołując metodęsetMediaButtonReceiver()
i przekazując muPendingIntent
Jeśli korzystasz z systemu w systemie starszym niż Android 5.0:
- Aby obsługiwać przyciski multimediów, zastąp parametr
onKeyDown()
aktywności - Statycznie utwórz obiekt
MediaButtonReceiver
, dodając go do pliku manifestu aplikacji.