Sterowanie multimediami za pomocą MediaSession

1. Wprowadzenie

Ostatnia aktualizacja: 2020-09-09

Jakie korzyści daje dodanie MediaSession do odtwarzania wideo?

Sesje multimediów stanowią integralne połączenie między platformą Android a aplikacjami do multimediów. Informuje on Androida nie tylko o tym, że odtwarzane są multimedia (aby mógł przekazywać działania związane z multimediami do odpowiedniej sesji), ale także o tym, co jest odtwarzane i jak można tym sterować.

Udostępnianie sesji multimedialnej w aplikacji ma wiele zalet, z których będą mogli korzystać użytkownicy. Oto kilka świetnych przykładów.

Asystent Google

Użytkownicy mogą łatwo wchodzić w interakcje z multimediami w Twojej aplikacji za pomocą poleceń głosowych, takich jak „Wstrzymaj”, „Wznów” i „Następny”. Metadane z multimediów mogą też służyć do uzyskiwania odpowiedzi na pytania o to, co jest obecnie odtwarzane.

Android TV

W przypadku dużych ekranów aplikacja na Androida TV może korzystać z tradycyjnych pilotów, jeśli użytkownicy mają telewizory obsługujące HDMI-CEC. Polecenia wydawane za pomocą przycisków odtwarzania/wstrzymywania, zatrzymywania, następny i poprzedni są przekazywane do aplikacji.

Sterowanie multimediami na ekranie

Począwszy od Androida 4.0 (poziom interfejsu API 14), system może uzyskiwać dostęp do stanu odtwarzania i metadanych sesji multimedialnej. Ta funkcja umożliwia wyświetlanie na ekranie blokady elementów sterujących multimediami i grafiki. To zachowanie różni się w zależności od wersji Androida.

Media w tle

W każdym z tych scenariuszy można sterować multimediami, nawet jeśli aplikacja odtwarzająca multimedia działa w tle.

Przetwarzanie rozpowszechnione

Udostępnianie multimediów wraz z informacjami o tym, co jest odtwarzane i jak można to kontrolować, może połączyć urządzenia, dzięki czemu użytkownicy będą mogli wchodzić w interakcje z multimediami na różne sposoby.

Co utworzysz

W tym ćwiczeniu rozszerzysz istniejący przykład ExoPlayera, aby dodać obsługę sesji multimedialnej. Twoja aplikacja będzie:

  • prawidłowo odzwierciedlać stan aktywności sesji multimedialnej;
  • Przekazywanie elementów sterujących multimediami do ExoPlayera
  • Przekazywanie metadanych elementów w kolejce do sesji multimedialnej

Czego się nauczysz

  • Dlaczego sesje multimedialne zapewniają użytkownikom bogatsze wrażenia
  • Tworzenie sesji multimedialnej i zarządzanie jej stanem
  • Jak połączyć sesję multimedialną z ExoPlayerem
  • Jak uwzględnić metadane elementów w kolejce odtwarzania w sesji multimedialnej
  • Dodawanie dodatkowych (niestandardowych) działań

To ćwiczenie koncentruje się na pakiecie SDK MediaSession. Nieistotne koncepcje i bloki kodu, w tym szczegóły implementacji ExoPlayera, nie są omawiane, ale można je po prostu skopiować i wkleić.

Czego potrzebujesz

  • najnowsza wersja Androida Studio (3.5 lub nowsza);
  • Podstawowa wiedza na temat tworzenia aplikacji na Androida

2. Przygotowania

Jaki jest nasz punkt początkowy?

Punktem początkowym jest główna wersja demonstracyjna ExoPlayera. Ta wersja demonstracyjna zawiera filmy z elementami sterującymi odtwarzaniem na ekranie, ale nie korzysta z sesji multimedialnych od razu po wyjęciu z pudełka. To świetne miejsce, aby je dodać.

Pobieranie przykładu ExoPlayer

Na początek zacznijmy od przykładu ExoPlayera. Sklonuj repozytorium GitHub, wykonując poniższy kod.

git clone https://github.com/google/ExoPlayer.git

Otwórz wersję demonstracyjną

W Android Studio otwórz główny projekt demonstracyjny znajdujący się w demos/main.

Android Studio wyświetli prośbę o ustawienie ścieżki pakietu SDK. Jeśli napotkasz problemy, możesz skorzystać z zaleceń dotyczących aktualizowania IDE i narzędzi SDK.

10e3b5c652186d57.png

Jeśli pojawi się prośba o użycie najnowszej wersji Gradle, zaktualizuj ją.

Poświęć chwilę, aby poznać podstawowe założenia projektowe aplikacji. Zwróć uwagę, że są 2 aktywności: SampleChooserActivity i PlayerActivity. Pozostałą część tego laboratorium poświęcimy klasie PlayerActivity, w której odtwarzane są multimedia. Otwórz tę klasę i przejdź do następnej sekcji.

3. Tworzenie sesji multimedialnej i zarządzanie jej stanem

Tworzenie sesji multimedialnej

Otwórz pokój PlayerActivity.java. Ta klasa tworzy ExoPlayera i zarządza jego funkcjami, np. renderowaniem wideo na ekranie. W tym ćwiczeniu połączymy ExoPlayera z sesją multimedialną.

Zadeklaruj te 2 pola u góry klasy. W tej sekcji będziemy używać tych pól.

private MediaSessionCompat mediaSession;
private MediaSessionConnector mediaSessionConnector;

Musisz dodać zależność projektu „extension-mediasession” do pliku build.gradle na poziomie modułu „Module: demo”:

implementation project(path: ':extension-mediasession')

Pamiętaj, że Android Studio może pomóc Ci w automatycznym dodaniu tej zależności, jeśli najedziesz kursorem myszy na błąd związany z rozwiązywaniem problemu z MediaSessionConnector:

60055e4ad54fbb97.png

Na koniec rozwiąż problemy z importowaniem klas, dodając ten kod:

import android.support.v4.media.session.MediaSessionCompat;
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector;

Po utworzeniu aktywności chcemy utworzyć sesję multimedialną i łącznik sesji multimedialnej, który będzie pośredniczyć między sesją multimedialną a ExoPlayerem.

Najlepiej wstawić go w miejscu, w którym tworzony jest ExoPlayer. W naszej aplikacji demonstracyjnej możemy dodać kod na końcu initializePlayer(). Pamiętaj, aby dodać tę logikę po utworzeniu instancji odtwarzacza.

private void initializePlayer() {
  if (player == null) {
    ...
    player = ...
    ...
    mediaSession = new MediaSessionCompat(this, "sample");
    mediaSessionConnector = new MediaSessionConnector(mediaSession);
    mediaSessionConnector.setPlayer(player);
  }
  ...
}

Zwolnij sesję multimedialną

Zwalniaj sesję multimedialną, gdy nie jest już potrzebna. Gdy udostępnimy ExoPlayer w releasePlayer(), możemy też dodać ten kod:

private void releasePlayer() {
  if (mediaSession != null) {
    mediaSession.release();
  }
  ...
}

Zarządzanie stanem sesji multimedialnej

Po utworzeniu instancji sesji multimedialnej musimy zadbać o to, aby jej stan był prawidłowo odzwierciedlany podczas interakcji użytkownika z aktywnością.

Gdy użytkownik rozpocznie aktywność, sesja multimedialna powinna stać się aktywna:

@Override
public void onStart() {
  ...
  if (mediaSession != null) {
    mediaSession.setActive(true);
  }
}

Nasza aplikacja nie odtwarza multimediów w tle, dlatego ważne jest, aby sesja multimedialna stała się nieaktywna, gdy użytkownik opuści aktywność:

@Override
public void onStop() {
  super.onStop();
  if (mediaSession != null) {
    mediaSession.setActive(false);
  }
  ...
}

Uruchommy wersję demonstracyjną

  1. Podłącz urządzenie z Androidem lub uruchom emulator.
  2. Upewnij się, że na pasku narzędzi Android Studio jest wybrana opcja „demo”. cb1ec4e50886874f.png
  3. Na pasku narzędzi Androida Studio kliknij 9d8fb3a9ddf12827.png.
  4. Po uruchomieniu aplikacji na urządzeniu wybierz strumień wideo, który chcesz odtworzyć.
  5. Po rozpoczęciu odtwarzania możesz używać tych poleceń adb do sterowania sesją multimedialną:
adb shell media dispatch pause
adb shell media dispatch play
adb shell media dispatch play-pause
adb shell media dispatch fast-forward
adb shell media dispatch rewind
  1. Dowiedz się też, jak Android postrzega Twoją sesję multimedialną. Możesz sprawdzić, które działania są obsługiwane, sprawdzając pole działania. Liczba, którą tu widzisz, to kombinacja identyfikatorów działań zadeklarowanych w obiekcie PlaybackState. Aby zobaczyć działanie sesji multimedialnej: adb shell dumpsys media_session
  2. Jeśli używasz urządzenia fizycznego z mikrofonem, spróbuj wywołać Asystenta Google i wydać polecenia głosowe, np. „Wstrzymaj”. „Wznów”. „Przewiń do przodu o minutę”.

b8dda02a6fb0f6a4.png *Przykładowa aplikacja ExoPlayer działająca na Androidzie TV.*

4. w tym metadane elementów w kolejce odtwarzania;

Możemy teraz rozszerzyć obsługiwane funkcje sesji multimedialnej, w której wcześniej utworzyliśmy MediaSessionConnector w initializePlayer().

Dodawanie elementu TimelineQueueNavigator

ExoPlayer przedstawia strukturę multimediów jako oś czasu. Aby dowiedzieć się, jak to działa, przeczytaj informacje o obiekcie osi czasu ExoPlayera. Dzięki tej strukturze możemy otrzymywać informacje o zmianach w treściach i na żądanie udostępniać metadane dotyczące tego, co jest aktualnie odtwarzane.

W tym celu zdefiniujemy element TimelineQueueNavigator. Znajdź instancję MediaSessionConnector w initializePlayer() i dodaj implementację TimelineQueueNavigator po zainicjowaniu mediaSession.

mediaSessionConnector.setQueueNavigator(new TimelineQueueNavigator(mediaSession) {
  @Override
  public MediaDescriptionCompat getMediaDescription(Player player, int windowIndex) {
    return new MediaDescriptionCompat.Builder()
            .setTitle(player.getCurrentMediaItem().mediaMetadata.title)
            .setDescription("MediaDescription description for " + windowIndex)
            .setSubtitle("MediaDescription subtitle")
            .build();
  }
});

Rozwiąż problemy z importem klas, dodając:

import android.support.v4.media.MediaDescriptionCompat;
import com.google.android.exoplayer2.ext.mediasession.TimelineQueueNavigator;

Zwróć uwagę, że parametr windowIndex odpowiada elementowi o tym indeksie w kolejce odtwarzania.

Po dodaniu metadanych możesz sprawdzić, czy Asystent rozumie, co jest odtwarzane. Podczas odtwarzania filmu na Androidzie TV wywołaj Asystenta i zapytaj „Co jest odtwarzane?”.

6c7fc0cb853cbc38.png

5. Dostosowywanie działań

Być może Twój odtwarzacz nie obsługuje niektórych działań lub chcesz dodać obsługę kolejnych? Przyjrzyjmy się teraz bliżej sesji multimedialnej, w której wcześniej utworzyliśmy element MediaSessionConnector w initializePlayer().

Deklarowanie obsługiwanych działań

Spróbuj użyć mediaSessionConnector.setEnabledPlaybackActions(), aby dostosować działania, które ma obsługiwać sesja multimedialna.

Pamiętaj, że pełny zestaw to:

mediaSessionConnector.setEnabledPlaybackActions(
        PlaybackStateCompat.ACTION_PLAY_PAUSE
                | PlaybackStateCompat.ACTION_PLAY
                | PlaybackStateCompat.ACTION_PAUSE
                | PlaybackStateCompat.ACTION_SEEK_TO
                | PlaybackStateCompat.ACTION_FAST_FORWARD
                | PlaybackStateCompat.ACTION_REWIND
                | PlaybackStateCompat.ACTION_STOP
                | PlaybackStateCompat.ACTION_SET_REPEAT_MODE
                | PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE
);

Zobaczmy jeszcze raz, jak te dane są udostępniane platformie:

  1. Jak wcześniej, rozpocznij film.
  2. Sprawdź, jak Android widzi metadane z sesji multimedialnej, wykonując to polecenie: adb shell dumpsys media_session
  3. Znajdź wiersz zawierający metadane i sprawdź, czy tytuł i opis są uwzględnione i powiązane z com.google.android.exoplayer2.demo/sample.

Dodawanie dodatkowych działań

Sesję multimedialną możemy rozszerzyć o dodatkowe działania. W tej sekcji dodamy tylko obsługę napisów.

Napisy

Dodanie obsługi napisów do sesji multimedialnych umożliwia użytkownikom włączanie i wyłączanie ich za pomocą głosu. W miejscu, w którym zainicjowano łącznik sesji multimedialnej, dodaj ten kod:

mediaSessionConnector.setCaptionCallback(new MediaSessionConnector.CaptionCallback() {
      @Override
      public void onSetCaptioningEnabled(Player player, boolean enabled) {
        Log.d("MediaSession", "onSetCaptioningEnabled: enabled=" + enabled);
      }

      @Override
      public boolean hasCaptions(Player player) {
        return true;
      }

      @Override
      public boolean onCommand(Player player, ControlDispatcher controlDispatcher, String command, Bundle extras, ResultReceiver cb) {
        return false;
      }
    }
);

Na koniec rozwiąż problemy z brakującymi importami.

Możesz to sprawdzić, wywołując Asystenta Google na Androidzie TV i mówiąc „Włącz napisy”. Sprawdź Logcat pod kątem wiadomości, aby zobaczyć, jak wywołuje on Twój kod.

6. Gratulacje

Udało Ci się dodać sesje multimedialne do przykładu.

Zyskujesz ogromną funkcjonalność dzięki:

  • dodawanie sesji multimediów,
  • łączenie sesji multimedialnych z instancją ExoPlayera,
  • dodawanie metadanych i dodatkowych działań.

Znasz już najważniejsze kroki, które pozwolą Ci wzbogacić aplikację do multimediów i zapewnić użytkownikom większe możliwości.

Końcowa uwaga

To laboratorium zostało utworzone na podstawie przykładu z kodu źródłowego ExoPlayera. Nie musisz używać ExoPlayera z kodu źródłowego. Zamiast tego zalecamy pobranie zależności dla ExoPlayera i MediaSessionConnector, aby łatwiej było Ci korzystać z najnowszych wersji.

Aby to zrobić, zastąp zależności projektu, takie jak:

implementation project(modulePrefix + 'library-core')
implementation project(path: ':extension-mediasession')

pobierać dane z repozytoriów Maven, takich jak:

implementation 'com.google.android.exoplayer:exoplayer-core:2.+'
implementation 'com.google.android.exoplayer:extension-mediasession:2.+'

Dokumentacja