Tworzenie podstawowej aplikacji odtwarzacza multimediów za pomocą Media3 ExoPlayer

Jetpack Media3 definiuje interfejs Player, który opisuje podstawowe funkcje. do odtwarzania plików wideo i audio. Implementacja domyślna to ExoPlayer w Media3. Zalecamy korzystanie z odtwarzacza ExoPlayer, ponieważ zapewnia Wszechstronny zestaw funkcji, które obejmują większość przypadków użycia związanych z odtwarzaniem do dostosowania do wszelkich dodatkowych przypadków użycia. ExoPlayer też abstrakcyjna jest fragmentacja urządzeń i systemów operacyjnych, dzięki czemu kod działa spójnie w całym ekosystemie Androida. ExoPlayer zawiera:

Na tej stronie omawiamy niektóre kluczowe kroki tworzenia odtwarzania w aplikacji, a więcej szczegółów znajdziesz w pełnych przewodnikach ExoPlayer Media3,

Pierwsze kroki

Na początek dodaj zależność od modułów ExoPlayer, UI i Common Jetpack Media3 –

implementation "androidx.media3:media3-exoplayer:1.4.0"
implementation "androidx.media3:media3-ui:1.4.0"
implementation "androidx.media3:media3-common:1.4.0"

W zależności od zastosowania mogą być też potrzebne dodatkowe moduły z Media3, np. exoplayer-dash, aby odtwarzać transmisje w formacie DASH.

Zastąp 1.4.0 preferowaną wersją bibliotece. Zapoznaj się z informacjami o wersji aby zobaczyć najnowszą wersję.

Tworzenie odtwarzacza multimediów

W Media3 możesz użyć dołączonej implementacji interfejsu Player interfejsu ExoPlayer, ale możesz też utworzyć własną implementację.

Tworzenie ExoPlayer

Najprostszy sposób utworzenia instancji ExoPlayer jest następujący:

Kotlin

val player = ExoPlayer.Builder(context).build()

Java

ExoPlayer player = new ExoPlayer.Builder(context).build();

Odtwarzacz możesz utworzyć w metodzie cyklu życia onCreate() funkcji Activity, Fragment lub Service, gdzie znajduje się ta aplikacja.

Builder zawiera Szeroka gama opcji dostosowywania, które mogą Cię zainteresować, takie jak:

Media3 udostępnia komponent interfejsu PlayerView, który możesz dodać do komponentu pliku układu. Ten komponent zawiera obiekt PlayerControlView, który umożliwia odtwarzanie elementy sterujące, SubtitleView do wyświetlania napisów oraz Surface do renderowania film.

Przygotowywanie odtwarzacza

Dodaj elementy multimedialne do playlisty: za pomocą takich metod jak: setMediaItem(). i addMediaItem(). Następnie zadzwoń pod numer prepare(), aby aby rozpocząć ładowanie multimediów i pozyskać niezbędne zasoby.

Nie należy wykonywać tych czynności przed uruchomieniem aplikacji na pierwszym planie. Jeśli odtwarzacz znajduje się w zasobniku Activity lub Fragment, oznacza to przygotowanie go na Metoda cyklu życia onStart() na poziomie API 24 lub wyższym lub onResume() metody cyklu życia na poziomie API 23 i niższym. W przypadku gracza, który znajduje się w grupie Service, możesz przygotować: onCreate().

Sterowanie odtwarzaczem

Po przygotowaniu odtwarzacza możesz sterować odtwarzaniem, korzystając z metod wywoływania w odtwarzaczu, na przykład:

Komponenty interfejsu, takie jak PlayerView i PlayerControlView, zostaną zaktualizowane odpowiednio po powiązaniu z odtwarzaczem.

Zwolnij odtwarzacz

Odtwarzanie może wymagać zasobów, których dostępność jest ograniczona, np. wideo z dekoderów, dlatego ważne jest wywołanie metody release() na odtwarzacz, by zwolnić zasoby, gdy nie będzie już potrzebny.

Jeśli odtwarzacz znajduje się w: Activity lub Fragment, puść go w Metoda cyklu życia onStop() na poziomie API 24 lub wyższym lub onPause() na poziomie API 23 i niższym. W przypadku gracza, który znajduje się w grupie Service, możesz opublikować go w aplikacji onDestroy().

Zarządzanie odtwarzaniem w ramach sesji multimediów

Sesje multimedialne na Androidzie to standardowy sposób interakcji z multimediami. mogą przekraczać granice procesów. Łączenie sesji multimediów z odtwarzaczem umożliwia reklamowanie multimediów odtwarzanych na zewnątrz i odtwarzanie ich polecenia ze źródeł zewnętrznych, na przykład w celu integracji z systemowe elementy sterujące multimediami na urządzeniach mobilnych i dużych urządzenia ekranów.

Aby używać sesji multimediów, dodaj zależność w module Sesja Media3:

implementation "androidx.media3:media3-session:1.4.0"

Tworzenie sesji multimediów

MediaSession możesz utworzyć po zainicjowaniu odtwarzacza w ten sposób:

Kotlin

val player = ExoPlayer.Builder(context).build()
val mediaSession = MediaSession.Builder(context, player).build()

Java

ExoPlayer player = new ExoPlayer.Builder(context).build();
MediaSession mediaSession = new MediaSession.Builder(context, player).build();

Media3 automatycznie synchronizuje stan elementu Player ze stanem MediaSession Działa to z każdą implementacją Player, w tym: ExoPlayer, CastPlayer lub do własnych zastosowań.

Przyznaj kontrolę innym klientom

Aplikacje klienckie mogą implementować kontroler multimediów aby sterować odtwarzaniem sesji multimediów. Aby otrzymywać te żądania, ustaw callback, gdy tworząc swoje urządzenie MediaSession.

Gdy kontroler ma się połączyć z sesją multimediów, onConnect() . Za pomocą tego narzędzia możesz: ControllerInfo podjąć decyzję o zaakceptowaniu lub odrzuć do ich przesłania. Zobacz ten przykład w aplikacji demonstracyjnej sesji Media3.

Po podłączeniu kontroler może wysyłać do sesji polecenia odtwarzania. sesja, następnie przekazuje te polecenia do odtwarzacza. Odtwarzanie i playlista polecenia zdefiniowane w interfejsie Player są automatycznie obsługiwane przez .

Inne metody wywołania zwrotnego umożliwiają obsługę na przykład żądań dotyczących niestandardowe polecenia odtwarzania i modyfikowaniu playlisty. Te wywołania zwrotne również zawierają obiekt ControllerInfo, więc może określić kontrolę dostępu na poziomie poszczególnych żądań.

Odtwarzanie multimediów w tle

Aby kontynuować odtwarzanie multimediów, gdy aplikacja nie działa na pierwszym planie, na przykład na odtwarzanie muzyki, audiobooków lub podcastów, nawet jeśli użytkownik nie ma Twojej aplikacji otwartego, pola Player i MediaSession powinny znaleźć się w tagu usługę działającą na pierwszym planie. Media3 udostępnia MediaSessionService.

Wdrażanie: MediaSessionService

Utwórz klasę, która rozszerza zakres MediaSessionService i tworzy instancję MediaSession w metodzie cyklu życia onCreate().

Kotlin

class PlaybackService : MediaSessionService() {
    private var mediaSession: MediaSession? = null

    // Create your Player and MediaSession in the onCreate lifecycle event
    override fun onCreate() {
        super.onCreate()
        val player = ExoPlayer.Builder(this).build()
        mediaSession = MediaSession.Builder(this, player).build()
    }

    // Remember to release the player and media session in onDestroy
    override fun onDestroy() {
        mediaSession?.run {
            player.release()
            release()
            mediaSession = null
        }
        super.onDestroy()
    }
}

Java

public class PlaybackService extends MediaSessionService {
    private MediaSession mediaSession = null;

    @Override
    public void onCreate() {
        super.onCreate();
        ExoPlayer player = new ExoPlayer.Builder(this).build();
        mediaSession = new MediaSession.Builder(this, player).build();
    }

    @Override
    public void onDestroy() {
        mediaSession.getPlayer().release();
        mediaSession.release();
        mediaSession = null;
        super.onDestroy();
    }
}

W pliku manifestu jest klasa Service z intencją MediaSessionService filtr i poproś o uprawnienie FOREGROUND_SERVICE w celu uruchomienia pierwszego planu usługa:

<service
    android:name=".PlaybackService"
    android:foregroundServiceType="mediaPlayback"
    android:exported="true">
    <intent-filter>
        <action android:name="androidx.media3.session.MediaSessionService"/>
    </intent-filter>
</service>

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

Na koniec zastąp metodę onGetSession() w utworzonej klasie, aby kontrolować dostępu klienta do sesji multimedialnej. Zwróć MediaSession, aby zaakceptować lub poproś o połączenie: null, aby ją odrzucić.

Kotlin

// This example always accepts the connection request
override fun onGetSession(
    controllerInfo: MediaSession.ControllerInfo
): MediaSession? = mediaSession

Java

@Override
public MediaSession onGetSession(MediaSession.ControllerInfo controllerInfo) {
  // This example always accepts the connection request
  return mediaSession;
}

Łączę z interfejsem

Teraz gdy sesja multimediów znajduje się w innym miejscu niż Service lub Activity Fragment – tam, gdzie znajduje się interfejs odtwarzacza, możesz użyć linku MediaController razem. W metodzie onStart() Activity lub Fragment z Twoim UI, utwórz SessionToken dla: MediaSession, a następnie użyj SessionToken aby zbudować MediaController. Trwa tworzenie MediaController asynchronicznie.

Kotlin

override fun onStart() {
  val sessionToken = SessionToken(this, ComponentName(this, PlaybackService::class.java))
  val controllerFuture = MediaController.Builder(this, sessionToken).buildAsync()
  controllerFuture.addListener(
    {
        // Call controllerFuture.get() to retrieve the MediaController.
        // MediaController implements the Player interface, so it can be
        // attached to the PlayerView UI component.
        playerView.setPlayer(controllerFuture.get())
      },
    MoreExecutors.directExecutor()
  )
}

Java

@Override
public void onStart() {
  SessionToken sessionToken =
    new SessionToken(this, new ComponentName(this, PlaybackService.class));
  ListenableFuture<MediaController> controllerFuture =
    new MediaController.Builder(this, sessionToken).buildAsync();
  controllerFuture.addListener(() -> {
    // Call controllerFuture.get() to retrieve the MediaController.
    // MediaController implements the Player interface, so it can be
    // attached to the PlayerView UI component.
    playerView.setPlayer(controllerFuture.get());
  }, MoreExecutors.directExecutor())
}

MediaController implementuje interfejs Player, więc możesz użyć tego samego takie jak play() i pause(), aby sterować odtwarzaniem. Podobne do innych Komponenty, pamiętaj, by zwolnić MediaController, gdy już nie jest takich jak metoda cyklu życia onStop() dla Activity, przez wywołanie MediaController.releaseFuture()

Publikowanie powiadomienia

Usługi działające na pierwszym planie są wymagane do publikowania powiadomień, gdy są aktywne. O MediaSessionService automatycznie utworzy MediaStyle powiadomienie dla w postaci MediaNotification. Aby podać niestandardowe powiadomienie, utwórz MediaNotification.Provider z DefaultMediaNotificationProvider.Builder lub tworząc niestandardową implementację interfejsu dostawcy. Dodaj: operatora sieci MediaSession za pomocą setMediaNotificationProvider

Reklamowanie biblioteki treści

MediaLibraryService opiera się na MediaSessionService, zezwalając klientowi do przeglądania multimediów udostępnianych przez tę aplikację. Aplikacje klienckie implementują MediaBrowser do interakcji dzięki urządzeniu MediaLibraryService.

Implementacja MediaLibraryService przebiega podobnie do wdrażania MediaSessionService, ale w onGetSession() musisz zwrócić błąd MediaLibrarySession zamiast MediaSession. W porównaniu do MediaSession.Callback, MediaLibrarySession.Callback zawiera dodatkowe które umożliwiają klientowi przeglądarki poruszanie się po treściach oferowanych przez w usłudze bibliotecznej.

Podobnie jak MediaSessionService, zadeklaruj MediaLibraryService w plik manifestu i poproś o uprawnienie FOREGROUND_SERVICE do uruchomienia pierwszego planu. usługa:

<service
    android:name=".PlaybackService"
    android:foregroundServiceType="mediaPlayback"
    android:exported="true">
    <intent-filter>
        <action android:name="androidx.media3.session.MediaLibraryService"/>
        <action android:name="android.media.browse.MediaBrowserService"/>
    </intent-filter>
</service>

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

Powyższy przykład zawiera filtr intencji zarówno dla elementu MediaLibraryService, a dla zapewnienia zgodności wstecznej – starsza wersja MediaBrowserService. dodatkowy filtr intencji włącza aplikacje klienckie używające interfejsu API MediaBrowserCompat aby rozpoznać urządzenie Service.

MediaLibrarySession umożliwia wyświetlanie biblioteki treści w drzewie o strukturze z pojedynczym pierwiaskiem MediaItem. Każdy element MediaItem w drzewie może mieć dowolna liczba podrzędnych węzłów MediaItem. Możesz obsługiwać inny poziom główny lub w zależności od żądania aplikacji klienta. Na przykład drzewo, wróć do klienta szukającego listy zalecanych elementów multimedialnych, może tylko zawierają węzeł główny MediaItem i jeden poziom podrzędnych węzłów MediaItem, natomiast drzewo, do którego wracasz do innej aplikacji klienckiej, może reprezentować całą bibliotekę treści.

Tworzę MediaLibrarySession

MediaLibrarySession Rozszerza interfejs API MediaSession o interfejsy API przeglądania treści. W porównaniu z MediaSession oddzwonienie, MediaLibrarySession oddzwonienie dodaje metody, takie jak:

  • onGetLibraryRoot() gdy klient żąda głównego elementu MediaItem drzewa treści
  • onGetChildren() dla sytuacji, gdy klient żąda elementów podrzędnych MediaItem w drzewie treści
  • onGetSearchResult() w przypadku, gdy klient zażąda wyników wyszukiwania z drzewa treści dla danego zapytanie

Odpowiednie metody wywołania zwrotnego obejmują LibraryParams obiekt z dodatkowymi sygnałami dotyczącymi typu drzewa treści, które aplikacja kliencka w Twojej okolicy.