Odtwarzacz to komponent aplikacji, który umożliwia odtwarzanie elementów multimedialnych.
Interfejs Player Media3 określa funkcje, które są zwykle obsługiwane przez odtwarzacz. Obejmuje to:
- wpływ na elementy sterujące odtwarzaniem, takie jak odtwarzanie, wstrzymywanie i przewijanie;
- wykonywanie zapytań o właściwości aktualnie odtwarzanych multimediów, takie jak pozycja odtwarzania;
- zarządzanie playlistą lub kolejką elementów multimedialnych,
- konfigurowanie właściwości odtwarzania, takich jak odtwarzanie losowe, powtarzanie, szybkość i głośność;
- renderowanie filmu na ekranie;
Media3 udostępnia też implementację interfejsu Player o nazwie
ExoPlayer.
wspólny interfejs między komponentami,
Interfejs Player implementuje kilka komponentów w Media3, np.:
| Komponent | Opis i uwagi dotyczące zachowania |
|---|---|
ExoPlayer |
Interfejs API odtwarzacza multimediów i domyślna implementacja interfejsu Player. |
MediaController |
Współpracuje z MediaSession, aby wysyłać polecenia odtwarzania. Jeśli elementy Player i MediaSession znajdują się w Service innym niż Activity lub Fragment, w którym znajduje się interfejs odtwarzacza, możesz przypisać element MediaController jako odtwarzacz do komponentu interfejsu, takiego jak PlayerView lub Player
Composable. Wywołania metod odtwarzania i playlist są wysyłane na urządzenie Player przez urządzenie MediaSession.
|
MediaBrowser |
Oprócz funkcji oferowanych przez
MediaController wchodzi w interakcję z
MediaLibrarySession, aby przeglądać dostępne treści multimedialne.
|
SimpleBasePlayer |
Implementacja Player, która zmniejsza liczbę metod do zaimplementowania do minimum. Przydatne, gdy używasz niestandardowego odtwarzacza, który chcesz połączyć z MediaSession.
|
ForwardingSimpleBasePlayer |
SimpleBasePlayer podklasa zaprojektowana do przekazywania operacji odtwarzania do innego elementu Player, przy jednoczesnym zachowaniu tych samych spójnych dostosowań zachowania co SimpleBasePlayer. Użyj tej klasy, aby pominąć lub zmodyfikować określone operacje odtwarzania.
|
RemoteCastPlayer |
Implementacja Player do sterowania odtwarzaniem w zdalnej aplikacji odbiornika Cast.
|
CastPlayer |
Implementacja Player do sterowania odtwarzaniem Cast zarówno lokalnie, jak i zdalnie.
|
Chociaż MediaSession nie implementuje interfejsu Player, podczas tworzenia
wymagany jest Player. Jego celem jest zapewnienie dostępu do Player
z innych procesów lub wątków.
Architektura odtwarzania Media3
Jeśli masz dostęp do obiektu Player, wywołuj jego metody bezpośrednio, aby wydawać polecenia odtwarzania. Możesz reklamować odtwarzanie i przyznawać źródłom zewnętrznym kontrolę nad odtwarzaniem, wdrażając MediaSession. Te źródła zewnętrzne implementują MediaController, który ułatwia łączenie się z sesją multimedialną i wydawanie poleceń odtwarzania.
Podczas odtwarzania multimediów w tle sesja multimedialna i odtwarzacz muszą znajdować się w MediaSessionService lub MediaLibraryService, które działają jako usługa na pierwszym planie. W takim przypadku możesz oddzielić odtwarzacz od aktywności w aplikacji, która zawiera interfejs sterowania odtwarzaniem. Może to wymagać użycia kontrolera multimediów.
Player odgrywa kluczową rolę w architekturze Media3.Stan odtwarzacza
Stan odtwarzacza multimediów implementującego interfejs Player składa się głównie z 4 kategorii informacji:
- Stan odtwarzania
- Odzyskaj za pomocą
getPlaybackState(). - Wartości stanu zdefiniowane przez interfejs to
STATE_IDLE,STATE_BUFFERING,STATE_READYiSTATE_ENDED.
- Odzyskaj za pomocą
- Playlista elementów multimedialnych
- Sekwencja instancji
MediaItemdo odtwarzania. - Odzyskaj za pomocą
getCurrentTimeline() - Instancje
Playermogą udostępniać metody operacji na playlistach, takie jak dodawanie i usuwanieMediaItem, oraz metody ułatwiające korzystanie, takie jakgetCurrentMediaItem().
- Sekwencja instancji
- właściwości odtwarzania/wstrzymywania, takie jak:
playWhenReady: określa, czy użytkownik chce, aby multimedia były odtwarzane, gdy jest to możliwe, czy mają pozostać wstrzymane.- Przyczyna wstrzymania odtwarzania:
wskazanie przyczyny wstrzymania odtwarzania (w odpowiednich przypadkach), nawet jeśli wartość parametru
playWhenReadytotrue. isPlaying: – informacja o tym, czy odtwarzacz jest aktualnie włączony. Wartośćtruebędzie miała tylko wtedy, gdy stan odtwarzania toSTATE_READY, wartośćplayWhenReadytotrue, a odtwarzanie nie jest wstrzymane.
- Pozycja odtwarzania, w tym:
- Bieżący indeks elementu multimedialnego:
Indeks bieżącego
MediaItemna playliście. isPlayingAd: informacja o tym, czy wstawiona reklama jest odtwarzana.- Bieżąca pozycja odtwarzania:
Bieżąca pozycja odtwarzania w obrębie bieżącego
MediaItemlub wstawionej reklamy.
- Bieżący indeks elementu multimedialnego:
Indeks bieżącego
Dodatkowo interfejs Player umożliwia dostęp do dostępnych ścieżek, metadanych multimediów, szybkości odtwarzania, głośności i innych właściwości pomocniczych odtwarzania.
Sprawdzanie zmian
Użyj Player.Listener, aby monitorować zmiany w Player. Więcej informacji o tworzeniu i używaniu odbiornika znajdziesz w dokumentacji ExoPlayera dotyczącej zdarzeń odtwarzacza.
Pamiętaj, że interfejs odbiornika nie zawiera żadnych wywołań zwrotnych do śledzenia normalnego postępu odtwarzania. Aby stale monitorować postęp odtwarzania, np. skonfigurować interfejs paska postępu, należy w odpowiednich odstępach czasu wysyłać zapytania o bieżącą pozycję.
Kotlin
fun checkPlaybackPosition(delayMs: Long): Boolean = handler.postDelayed( { val currentPosition = player.currentPosition // Update UI based on currentPosition checkPlaybackPosition(delayMs) }, delayMs, )
Java
boolean checkPlaybackPosition(long delayMs) { return handler.postDelayed( () -> { long currentPosition = player.getCurrentPosition(); // Update UI based on currentPosition checkPlaybackPosition(delayMs); }, delayMs); }
sterować odtwarzaniem.
Interfejs Player oferuje wiele sposobów manipulowania stanem i sterowania odtwarzaniem:
- Podstawowe elementy sterujące odtwarzaniem, takie jak
play(),pause(),prepare()istop(). - Operacje na playlistach, takie jak
addMediaItem()lubremoveMediaItem(). - Przewijanie, aby zmienić bieżący element lub pozycję.
- Ustaw tryby powtarzania i tryb odtwarzania losowego.
- Zaktualizuj ustawienia wyboru ścieżki.
- Ustaw szybkość odtwarzania.
Implementacje niestandardowe Player
Aby utworzyć niestandardowy odtwarzacz, możesz rozszerzyć klasę SimpleBasePlayer
zawartą w Media3. Ta klasa zapewnia podstawową implementację interfejsu Player, aby zredukować do minimum liczbę metod, które musisz zaimplementować.
Zacznij od zastąpienia metody getState(). Ta metoda powinna wypełniać stan bieżącego odtwarzacza po wywołaniu, w tym:
- Zestaw dostępnych poleceń
- właściwości odtwarzania, takie jak to, czy odtwarzacz ma rozpocząć odtwarzanie, gdy stan odtwarzania to
STATE_READY, indeks aktualnie odtwarzanego elementu multimedialnego i pozycja odtwarzania w bieżącym elemencie;
Kotlin
class CustomPlayer(looper: Looper) : SimpleBasePlayer(looper) { override fun getState(): State { return State.Builder() .setAvailableCommands(Commands.EMPTY) // Set which playback commands the player can handle // Configure additional playback properties .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST) .setCurrentMediaItemIndex(0) .setContentPositionMs(0) .build() } }
Java
private static final class CustomPlayer extends SimpleBasePlayer { public CustomPlayer(Looper looper) { super(looper); } @Override protected State getState() { return new State.Builder() .setAvailableCommands(Commands.EMPTY) // Set which playback commands the player can handle // Configure additional playback properties .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST) .setCurrentMediaItemIndex(0) .setContentPositionMs(0) .build(); } }
SimpleBasePlayer zapewni, że State zostanie utworzony z prawidłową kombinacją wartości stanu. Zajmuje się też odbiorcami i informowaniem ich o zmianach stanu. Jeśli chcesz ręcznie wywołać aktualizację stanu, wywołaj invalidateState().
Oprócz metody getState() musisz wdrożyć tylko te metody, które są używane w przypadku poleceń, które odtwarzacz deklaruje jako dostępne. Znajdź metodę obsługi, którą można zastąpić, odpowiadającą funkcji, którą chcesz zaimplementować. Na przykład zastąp metodę handleSeek(), aby obsługiwać operacje takie jak COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM i COMMAND_SEEK_TO_NEXT_MEDIA_ITEM.
Modyfikowanie implementacji Player
Zamiast tworzyć całkowicie niestandardowy Player, możesz użyć ForwardingSimpleBasePlayer, aby zmodyfikować stan i działanie istniejącego Player. Więcej informacji znajdziesz w przewodniku na stronie dostosowywania.