Reakcja na przyciski multimediów

Przyciski multimediów to przyciski sprzętowe dostępne na urządzeniach z Androidem i innych urządzeniach peryferyjnych, np. przycisk wstrzymania/odtwarzania na słuchawkach Bluetooth. Gdy użytkownik naciśnie przycisk multimediów, Android wygeneruje KeyEvent, który zawiera kod klucza identyfikujący przycisk. Kody klucza w przypadku przycisku mediów są stałymi, które zaczynają się od KEYCODE_MEDIA (np. KEYCODE_MEDIA_PLAY).

Aplikacje powinny obsługiwać zdarzenia przycisku multimediów w 3 przypadkach, w tej kolejności priorytet:

  • Gdy aktywność w interfejsie aplikacji 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 trzeba ją ponownie uruchomić

Obsługa przycisków multimediów w aktywności na pierwszym planie

Aktywność na pierwszym planie odbiera kluczowe zdarzenie przycisku multimediów w elemencie onKeyDown() . W zależności od uruchomionej wersji Androida system może kierować zdarzenie na 2 sposoby. za pomocą kontrolera multimediów:

  • Jeśli używasz Androida 5.0 (poziom interfejsu API 21) lub nowszego, wywołaj FLAG_HANDLES_MEDIA_BUTTONS MediaBrowserCompat.ConnectionCallback.onConnected Dzięki temu automatycznie wywołuje dispatchMediaButtonEvent(), co przekłada kod klucza na wywołanie zwrotne sesji multimediów.
  • Przed Androidem 5.0 (poziom interfejsu API 21) trzeba zmodyfikować onKeyDown(), aby obsługiwały samemu utworzyć wydarzenie. Więcej informacji znajdziesz w artykule Obsługa przycisków multimediów w aktywnej sesji multimediów. Poniższy fragment kodu pokazuje, jak przechwycić i wywołaj dispatchMediaButtonEvent(). Pamiętaj, aby zwrócić adres true do wskazują, że zdarzenie zostało obsługiwane:

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

Znajdowanie sesji multimedialnej

Jeśli działanie na pierwszym planie nie obsługuje zdarzenia, Android próbuje znaleźć która potrafi ją obsłużyć. W zależności od działającej wersji Na Androidzie dostępne są 2 sposoby wyszukiwania sesji multimediów:

  • Jeśli korzystasz z Androida 8.0 (poziom interfejsu API 26) lub nowszego, system próbuje znaleźć ostatnią aplikację za pomocą sesji MediaSession, która odtwarzała dźwięk lokalnie. Jeśli podczas sesji jest nadal aktywny. Android wysyła wydarzenie bezpośrednio do niego. W przeciwnym razie, jeśli sesja nie jest aktywna i ma odbiornik przycisku multimedialnego, Android wysyła zdarzenie do odbiorcy, co spowoduje ponowne uruchomienie sesji i umożliwi odebranie zdarzenia. Więcej informacji znajdziesz w artykule Ponowne uruchamianie nieaktywnej sesji multimediów przy użyciu przycisków multimediów. Jeśli sesja nie ma modułu obsługującego przycisk multimediów, system odrzuca multimedia. i nic się nie wydarzy. Logika ukazuje się w ten sposób: schemat:

  • W wersjach starszych niż Android 8.0 (poziom interfejsu API 26) system próbuje wysyłać zdarzenie do podczas sesji multimedialnej. Jeśli jest wiele aktywnych sesji multimediów, Android spróbuje aby wybrać sesję multimediów, która przygotowuje się do odtwarzania (buforowanie/łączenie), odtwarzania lub wstrzymania, a nie takiego, który został wstrzymany. (Zobacz Obsługa przycisków multimediów w aktywnej sesji multimediów ). Jeśli nie ma aktywnych Android próbuje wysłać zdarzenie do ostatnio aktywnej sesji. Więcej informacji znajdziesz w artykule Ponowne uruchamianie nieaktywnej sesji multimediów przy użyciu przycisków multimediów. Logikę pokazano na tym diagramie:

Obsługa przycisków multimediów w aktywnej sesji multimediów

W Androidzie 5.0 (poziom interfejsu API 21) i nowszych Android automatycznie wysyła zdarzenia przycisku multimediów do aktywnej sesji multimediów przez wywołanie 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 przez transmitowanie intencji z działaniem ACTION_MEDIA_BUTTON. Aplikacja musi zarejestrować Odbiornik BroadcastReceiver na przechwytywanie tych intencji. MediaButtonReceiver została opracowana specjalnie w tym celu. Jest to klasa udogodnienia dla osób, które Androida biblioteki kompatybilnej z multimediami, obsługuje intencję ACTION_MEDIA_BUTTON i przekształca przychodzące intencje na odpowiednie wywołania metody MediaSessionCompat.Callback.

MediaButtonReceiver to krótkotrwały BroadcastReceiver. Przekazuje ona wiadomości przychodzące z intencjami do usługi, która zarządza Twoją sesją multimediów. Jeśli chcesz korzystać z usługi w systemach Android 5.0 starszych niż 5.0 należy dodać parametr MediaButtonReceiver w pliku manifestu 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>

Interfejs BroadcastReceiver przekazuje intencję do Twojej usługi. Aby przeanalizować intencję i wygeneruj wywołanie zwrotne do sesji multimediów, umieść metodę MediaButtonReceiver.handleIntent() w tagu onStartCommand() usługi. Konwertuje to kod klucza na 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 uruchomienia nieaktywnej sesji multimediów

Jeśli Android rozpozna ostatnią aktywną sesję multimediów, próbuje ponownie uruchomić 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 jest niewidoczny (dotyczy to większości aplikacji audio).

To zachowanie jest automatycznie włączane, gdy używasz MediaSessionCompat. Jeśli korzysta z MediaSession platformy Androida lub biblioteki pomocy w wersji od 24.0.0 do 25.1.1 należy wywołać setMediaButtonReceiver, aby umożliwić ponowne uruchomienie przycisku multimediów nieaktywna sesja multimediów.

Tę funkcję możesz wyłączyć w Androidzie 5.0 (poziom interfejsu API 21) lub nowszym przez jak ustawić odbiornik przycisku multimedialnego z pustym ekranem:

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 funkcji onMediaButtonEvent() powoduje wyodrębnienie kodu klucza i określenie, którą metodę należy wywołać, na podstawie bieżącego stanu sesji multimediów oraz listy obsługiwanych działań. Na przykład KEYCODE_MEDIA_PLAY wywołuje onPlay().

Aby przycisk multimediów był spójny we wszystkich aplikacjach, użyj zachowanie domyślne i odbiegają tylko w konkretnym celu. Jeśli przycisk multimediów wymaga niestandardowej obsługi, zastąp wywołanie zwrotne onMediaButtonEvent() wyodrębnij KeyEvent za pomocą intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT), samodzielnie obsługuje zdarzenie i zwróci wartość true.

Podsumowanie

Aby zapewnić prawidłową obsługę zdarzeń przycisków multimediów we wszystkich wersjach Androida, musisz: podaj FLAG_HANDLES_MEDIA_BUTTONS podczas tworzenia sesji multimediów.

Poza tym w zależności od tego, jakie wersje Androida chcesz obsługiwać, musisz też spełnić te wymagania:

W Androidzie 5.0 lub nowszym:

  • Wywołaj funkcję MediaControllerCompat.setMediaController() z poziomu wywołania zwrotnego kontrolera multimediów onConnected()
  • Aby umożliwić przyciskowi multimediów ponowne uruchomienie nieaktywnej sesji, dynamicznie utwórz MediaButtonReceiver, wywołując setMediaButtonReceiver() z wynikiem pozytywnym PendingIntent

W systemach starszych niż Android 5.0:

  • Zastąp onKeyDown() aktywności, aby obsługiwać przyciski multimediów
  • Statycznie utwórz element MediaButtonReceiver, dodając go do pliku manifestu aplikacji.