Aplikacje, które obecnie używają samodzielnej biblioteki com.google.android.exoplayer2
i biblioteki androidx.media
, należy przenieść do androidx.media3
. Aby przenieść pliki kompilacji Gradle, pliki źródłowe Java i Kotlin oraz pliki układu XML z ExoPlayer 2.19.1
na platformę AndroidX Media3 1.1.1
, użyj skryptu migracji.
Przegląd
Przed migracją zapoznaj się z poniższymi sekcjami, aby dowiedzieć się więcej o zaletach nowych interfejsów API, ich migracji oraz wymaganiach wstępnych, jakie musi spełnić projekt aplikacji.
Dlaczego warto przejść na Jetpack Media3
- To nowa strona ExoPlayer, natomiast
com.google.android.exoplayer2
została wycofana. - Uzyskaj dostęp do Player API w różnych komponentach/procesach za pomocą
MediaBrowser
/MediaController
. - korzystać z rozszerzonych możliwości interfejsów API
MediaSession
iMediaController
. - Reklamuj możliwości odtwarzania za pomocą szczegółowej kontroli dostępu.
- Uprość swoją aplikację, usuwając właściwości
MediaSessionConnector
iPlayerNotificationManager
. - Zgodność wsteczna z interfejsami API klienta kompatybilnymi z mediami (
MediaBrowserCompat
/MediaControllerCompat
/MediaMetadataCompat
)
Interfejsy Media API zostaną przeniesione do AndroidX Media3
- ExoPlayer i jego rozszerzenia
Obejmuje to wszystkie moduły starszego projektu ExoPlayer z wyjątkiem wycofanego modułu mediasession. Aplikacje lub moduły w zależności od pakietów wcom.google.android.exoplayer2
można przenieść za pomocą skryptu migracji. - MediaSessionConnector (w zależności od pakietów
androidx.media.*
pakietuandroidx.media:media:1.4.3+
)
UsuńMediaSessionConnector
i użyjandroidx.media3.session.MediaSession
. - Media BrowserServiceCompat (w zależności od pakietów
androidx.media.*
androidx.media:media:1.4.3+
)
Przenieś podklasy klasyandroidx.media.MediaBrowserServiceCompat
doandroidx.media3.session.MediaLibraryService
i kod za pomocą koduMediaBrowserCompat.MediaItem
doandroidx.media3.common.MediaItem
. - Media BrowserCompat (w zależności od pakietów
android.support.v4.media.*
systemuandroidx.media:media:1.4.3+
)
Przeprowadź migrację kodu klienta za pomocąMediaBrowserCompat
lubMediaControllerCompat
, aby używaćandroidx.media3.session.MediaBrowser
zandroidx.media3.common.MediaItem
.
Wymagania wstępne
Sprawdzanie, czy projekt znajduje się pod kontrolą źródła
Zadbaj o to, aby zmiany wprowadzone przez narzędzia do migracji oparte na skryptach można było łatwo cofnąć. Jeśli jeszcze nie masz projektu pod kontrolą źródła, to dobry moment, by zacząć z niego korzystać. Jeśli z jakiegoś powodu nie chcesz tego robić, przed rozpoczęciem migracji utwórz kopię zapasową projektu.
Aktualizowanie aplikacji
Zalecamy zaktualizowanie projektu tak, by korzystał z najnowszej wersji biblioteki ExoPlayer, i usunięcie wszystkich wywołań wycofanych metod. Jeśli zamierzasz użyć skryptu podczas migracji, musisz dopasować wersję, do której aktualizujesz usługę, do wersji obsługiwanej przez skrypt.
Zwiększ parametr buildSdkVersion aplikacji do co najmniej 32.
Uaktualnij Gradle i wtyczkę Android Studio Gradle do najnowszej wersji, która współpracuje ze zaktualizowanymi zależnościami podanymi powyżej. Na przykład:
- Wersja wtyczki Androida do obsługi Gradle: 7.1.0
- Wersja Gradle: 7.4
Zastąp wszystkie instrukcje importowania symboli zastępczych, w których znajduje się asterix (*), i użyj w pełni kwalifikowanych instrukcji importu: usuń instrukcje importu z symbolami wieloznacznymi i użyj Android Studio, aby zaimportować w pełni kwalifikowane instrukcje (F2 – Alt/Enter, F2 – Alt/Enter itp.).
Przenieś z
com.google.android.exoplayer2.PlayerView
docom.google.android.exoplayer2.StyledPlayerView
. Jest to konieczne, ponieważ w AndroidX Media3 nie ma odpowiednikacom.google.android.exoplayer2.PlayerView
.
Migracja ExoPlayer z obsługą skryptów
Skrypt ułatwia przejście z com.google.android.exoplayer2
do nowego pakietu i struktury modułów w androidx.media3
. Skrypt stosuje w projekcie kilka testów weryfikacyjnych i wyświetla ostrzeżenia, jeśli weryfikacja się nie powiedzie.
W przeciwnym razie stosowane są mapowania zmienionych klas i pakietów w zasobach projektu Gradle na Androida zapisanego w języku Java lub Kotlin.
usage: ./media3-migration.sh [-p|-c|-d|-v]|[-m|-l [-x <path>] [-f] PROJECT_ROOT]
PROJECT_ROOT: path to your project root (location of 'gradlew')
-p: list package mappings and then exit
-c: list class mappings (precedence over package mappings) and then exit
-d: list dependency mappings and then exit
-l: list files that will be considered for rewrite and then exit
-x: exclude the path from the list of file to be changed: 'app/src/test'
-m: migrate packages, classes and dependencies to AndroidX Media3
-f: force the action even when validation fails
-v: print the exoplayer2/media3 version strings of this script
-h, --help: show this help text
Korzystanie ze skryptu migracji
Pobierz skrypt migracji z tagu projektu ExoPlayer na GitHubie odpowiadającego wersji, do której została zaktualizowana aplikacja:
curl -o media3-migration.sh \ "https://raw.githubusercontent.com/google/ExoPlayer/r2.19.1/media3-migration.sh"
Ustaw skrypt jako wykonywalny:
chmod 744 media3-migration.sh
Aby poznać opcje, uruchom skrypt z użyciem parametru
--help
.Uruchom skrypt z użyciem parametru
-l
, aby wyświetlić listę plików wybranych do migracji (użyj polecenia-f
, aby wymusić wyświetlanie strony bez ostrzeżeń):./media3-migration.sh -l -f /path/to/gradle/project/root
Uruchom skrypt z użyciem parametru
-m
, aby zmapować pakiety, klasy i moduły na Media3. Uruchomienie skryptu z opcją-m
spowoduje zastosowanie zmian do wybranych plików.- Zatrzymaj po wystąpieniu błędu weryfikacji bez wprowadzania zmian
./media3-migration.sh -m /path/to/gradle/project/root
- Wymuszone wykonanie
Jeśli skrypt wykryje naruszenie warunków wstępnych, migrację można wymusić za pomocą flagi
-f
:./media3-migration.sh -m -f /path/to/gradle/project/root
# list files selected for migration when excluding paths
./media3-migration.sh -l -x "app/src/test/" -x "service/" /path/to/project/root
# migrate the selected files
./media3-migration.sh -m -x "app/src/test/" -x "service/" /path/to/project/root
Po uruchomieniu skryptu z opcją -m
wykonaj te ręczne czynności:
- Sprawdź, jak skrypt zmienił Twój kod: użyj narzędzia różnic i rozwiąż potencjalne problemy (rozważ zgłoszenie błędu, jeśli uważasz, że w skrypcie występuje ogólny problem, który został wprowadzony bez podania opcji
-f
). - Utwórz projekt: użyj
./gradlew clean build
lub w Android Studio wybierz Plik > Synchronizuj projekt z plikami Gradle, a następnie Kompiluj > Oczyść projekt i Kompiluj > Przebuduj projekt (możesz sprawdzać kompilację na karcie „Kompilacja – dane wyjściowe kompilacji” w Android Studio.
Zalecane dodatkowe kroki:
- rozwiązać problem z akceptacją błędów dotyczących używania niestabilnych interfejsów API.
- Zastąp wycofane wywołania interfejsu API: użyj sugerowanego zastępczego interfejsu API. Aby dowiedzieć się, czego użyć zamiast danego wywołania, najedź kursorem na ostrzeżenie w Android Studio i zapoznaj się z dokumentem JavaDoc dotyczącym wycofanego symbolu.
- Posortuj instrukcje importu: otwórz projekt w Android Studio, a następnie kliknij prawym przyciskiem myszy węzeł folderu pakietów w widoku projektu i wybierz Optymalizuj importowanie przy pakietach, które zawierają zmienione pliki źródłowe.
Zamień MediaSessionConnector
na androidx.media3.session.MediaSession
W starszym świecie MediaSessionCompat
element MediaSessionConnector
odpowiadał za synchronizację stanu odtwarzacza ze stanem sesji oraz odbieranie poleceń od kontrolerów, które wymagały przekazania dostępu do odpowiednich metod odtwarzacza. W AndroidX Media3 MediaSession
robi to bezpośrednio bez konieczności stosowania oprogramowania sprzęgającego.
Usuń wszystkie odniesienia i użycie MediaSessionConnector: jeśli do przeniesienia klas i pakietów ExoPlayer użyto automatycznego skryptu, prawdopodobnie skrypt pozostawił kod w stanie nieskompilowania w związku z elementem
MediaSessionConnector
, którego nie można rozwiązać. Android Studio wyświetli uszkodzony kod przy próbie skompilowania lub uruchomienia aplikacji.W pliku
build.gradle
, w którym przechowujesz zależności, dodaj zależność implementacji do modułu sesji AndroidX Media3 i usuń starszą zależność:implementation "androidx.media3:media3-session:1.3.1"
Zastąp
MediaSessionCompat
elementemandroidx.media3.session.MediaSession
.W witrynie kodu, w której została utworzona starsza wersja
MediaSessionCompat
, użyjandroidx.media3.session.MediaSession.Builder
, aby utworzyćMediaSession
. Przekaż odtwarzacz, by utworzyć kreator sesji.val player = ExoPlayer.Builder(context).build() mediaSession = MediaSession.Builder(context, player) .setSessionCallback(MySessionCallback()) .build()
Zaimplementuj
MySessionCallback
zgodnie z wymaganiami aplikacji. Jest to opcjonalne. Jeśli chcesz zezwolić kontrolerom na dodawanie elementów multimedialnych do odtwarzacza, zaimplementujMediaSession.Callback.onAddMediaItems()
. Obsługuje różne obecne i starsze metody interfejsu API, które dodają elementy multimedialne do odtwarzacza w celu ich odtwarzania w sposób zgodny wstecznie. Obejmuje to metodyMediaController.set/addMediaItems()
kontrolera Media3, a także metodyTransportControls.prepareFrom*/playFrom*
starszego interfejsu API. Przykładową implementację interfejsuonAddMediaItems
znajdziesz wPlaybackService
aplikacji demonstracyjnej sesji.Zwolnij sesję multimediów w witrynie kodu, w której sesja została zniszczona przed migracją:
mediaSession?.run { player.release() release() mediaSession = null }
Funkcje MediaSessionConnector
w Media3
W tabeli poniżej znajdziesz interfejsy API Media3, które obsługują funkcje wcześniej zaimplementowane w MediaSessionConnector
.
Łącznik sesji MediaSession | AndroidX Media3 |
---|---|
CustomActionProvider |
MediaSession.Callback.onCustomCommand()/
MediaSession.setCustomLayout() |
PlaybackPreparer |
MediaSession.Callback.onAddMediaItems()
(prepare() jest wywoływany wewnętrznie)
|
QueueNavigator |
ForwardingPlayer |
QueueEditor |
MediaSession.Callback.onAddMediaItems() |
RatingCallback |
MediaSession.Callback.onSetRating() |
PlayerNotificationManager |
DefaultMediaNotificationProvider/
MediaNotification.Provider |
Przenieś MediaBrowserService
do MediaLibraryService
AndroidX Media3 wprowadza interfejs MediaLibraryService
, który zastępuje MediaBrowserServiceCompat
. Dokument JavaDoc klasy MediaLibraryService
i jego nadrzędna klasa MediaSessionService
stanowią dobre wprowadzenie do interfejsu API i asynchronicznego modelu programowania usługi.
Element MediaLibraryService
jest zgodny wstecz z MediaBrowserService
. Aplikacja kliencka, która używa MediaBrowserCompat
lub MediaControllerCompat
, może w dalszym ciągu działać bez zmian w kodzie po połączeniu się z MediaLibraryService
. Dla klienta jasne jest to, czy aplikacja używa MediaLibraryService
czy starszej wersji MediaBrowserServiceCompat
.
Aby zgodność wsteczna działała, musisz zarejestrować oba interfejsy usług w usłudze w
AndroidManifest.xml
. W ten sposób klient znajdzie Twoją usługę przez wymagany interfejs usługi:<service android:name=".MusicService" android:exported="true"> <intent-filter> <action android:name="androidx.media3.session.MediaLibraryService"/> <action android:name="android.media.browse.MediaBrowserService" /> </intent-filter> </service>
W pliku
build.gradle
, w którym przechowujesz zależności, dodaj zależność implementacji do modułu sesji AndroidX Media3 i usuń starszą zależność:implementation "androidx.media3:media3-session:1.3.1"
Zmień swoją usługę na dziedziczenie z
MediaLibraryService
zamiastMediaBrowserService
Jak wspomnieliśmy wcześniej, usługaMediaLibraryService
jest zgodna ze starszą wersjąMediaBrowserService
. W związku z tym szerszy interfejs API dostępny w usłudze jest nadal taki sam. Możliwe więc, że aplikacja zachowa większość logiki niezbędną do zaimplementowania elementuMediaBrowserService
i dostosowania go do nowej wersjiMediaLibraryService
.Główne różnice w porównaniu ze starszą wersją
MediaBrowserServiceCompat
są następujące:Zaimplementuj metody cyklu życia usługi: metody, które trzeba zastąpić w samej usłudze, to
onCreate/onDestroy
, gdzie aplikacja alokuje/uwalnia sesję biblioteki, odtwarzacz i inne zasoby. Oprócz standardowych metod cyklu życia usługi aplikacja musi zastąpić metodęonGetSession(MediaSession.ControllerInfo)
, aby zwrócić metodęMediaLibrarySession
utworzoną wonCreate
.Zaimplementuj MediaLibraryService.MediaLibrarySessionCallback: do utworzenia sesji wymagane jest narzędzie
MediaLibraryService.MediaLibrarySessionCallback
, które implementuje rzeczywiste metody interfejsu API domeny. Dlatego zamiast metody interfejsu API starszej usługi zastąpisz metody zMediaLibrarySession.Callback
.Wywołanie zwrotne jest następnie używane do utworzenia
MediaLibrarySession
:mediaLibrarySession = MediaLibrarySession.Builder(this, player, MySessionCallback()) .build()
Pełny interfejs API MediaLibrarySessionCallback znajdziesz w jego dokumentacji.
Wdróż
MediaSession.Callback.onAddMediaItems()
: wywołanie zwrotneonAddMediaItems(MediaSession, ControllerInfo, List<MediaItem>)
obsługuje różne obecne i starsze metody interfejsu API, które dodają elementy multimedialne do odtwarzacza, aby umożliwić odtwarzanie w sposób zgodny wstecznie. Obejmuje to metodyMediaController.set/addMediaItems()
kontrolera Media3 oraz metodyTransportControls.prepareFrom*/playFrom*
starszej wersji interfejsu API. Przykładową implementację wywołania zwrotnego znajdziesz wPlaybackService
aplikacji demonstracyjnej sesji.AndroidX Media3 korzysta z
androidx.media3.common.MediaItem
, a nie z Media BrowserCompat.MediaItem i MediaMetadataCompat. Fragmenty kodu powiązane ze starszymi klasami muszą zostać odpowiednio zmienione lub zmapować je na obiektMediaItem
Media3.Ogólny model programowania asynchronicznego został zmieniony na
Futures
, a nie w przeciwieństwie do metodyResult
stosowanej w modeluMediaBrowserServiceCompat
. Implementacja usługi może zwrócić asynchroniczny obiektListenableFuture
zamiast odłączać wynik lub zwrócić natychmiastową przyszłość, aby bezpośrednio zwrócić wartość.
Usunięcie PlayerPowiadomienieManagera
MediaLibraryService
automatycznie obsługuje powiadomienia o multimediach, a element PlayerNotificationManager
można usunąć, gdy używasz elementu MediaLibraryService
lub MediaSessionService
.
Aplikacja może dostosować powiadomienie, ustawiając w onCreate()
wartość niestandardową MediaNotification.Provider
, która zastępuje DefaultMediaNotificationProvider
. W razie potrzeby MediaLibraryService
uruchamia usługę na pierwszym planie.
Po zastąpieniu ustawienia MediaLibraryService.updateNotification()
aplikacja uzyska pełne prawo własności do publikowania powiadomień i uruchamiania/zatrzymywania usługi na pierwszym planie zgodnie z potrzebami.
Migracja kodu klienta przy użyciu przeglądarki Media Browser
W AndroidX Media3 interfejs MediaBrowser
zawiera interfejsy MediaController/Player
, za pomocą których można sterować odtwarzaniem multimediów poza przeglądaniem biblioteki multimediów. Jeśli w starszym świecie trzeba było utworzyć MediaBrowserCompat
i MediaControllerCompat
, możesz to zrobić, używając tylko elementu MediaBrowser
w Media3.
Można skompilować MediaBrowser
i poczekać na połączenie z usługą:
scope.launch {
val sessionToken =
SessionToken(context, ComponentName(context, MusicService::class.java)
browser =
MediaBrowser.Builder(context, sessionToken))
.setListener(BrowserListener())
.buildAsync()
.await()
// Get the library root to start browsing the library.
root = browser.getLibraryRoot(/* params= */ null).await();
// Add a MediaController.Listener to listen to player state events.
browser.addListener(playerListener)
playerView.setPlayer(browser)
}
Przeczytaj artykuł o sterowaniu odtwarzaniem w trakcie sesji multimediów, aby dowiedzieć się, jak utworzyć element MediaController
do sterowania odtwarzaniem w tle.
Dalsze kroki i czyszczenie
Błędy niestabilnego interfejsu API
Po migracji do Media3 mogą pojawić się błędy lint dotyczące niestabilnych zastosowań interfejsu API.
Te interfejsy API są bezpieczne w użyciu, a błędy lintowania są efektem naszych nowych gwarancji zgodności plików binarnych. Jeśli nie wymagasz ścisłej zgodności plików binarnych, te błędy można bezpiecznie pominąć za pomocą adnotacji @OptIn
.
Tło
Ani ExoPlayer w wersji 1, ani 2 nie gwarantuje rygorystycznej zgodności plików binarnych biblioteki między kolejnymi wersjami. Interfejs API ExoPlayer jest z założenia bardzo duży, umożliwiając aplikacjom dostosowywanie niemal każdego aspektu odtwarzania. Kolejne wersje ExoPlayer czasami wprowadzały zmiany nazw symboli lub inne zmiany powodujące niezgodność (np. nowe wymagane metody w interfejsach). W większości przypadków te awarie można było ograniczyć przez wprowadzenie nowego symbolu i wycofanie starego symbolu w kilku wersjach, aby dać deweloperom czas na migrację wykorzystania, ale nie zawsze było to możliwe.
Ta zmiana sprawiła, że użytkownicy bibliotek ExoPlayer w wersjach 1 i 2 mieli 2 problemy:
- Przejście z wersji ExoPlayer na wersję ExoPlayer może spowodować zatrzymanie kompilacji kodu.
- Aplikacja, która bazowała na ExoPlayer zarówno bezpośrednio, jak i za pomocą biblioteki pośredniej, musiała zadbać o tę samą wersję obu zależności. W przeciwnym razie niezgodności binarne mogłyby powodować awarie w czasie działania.
Ulepszenia w Media3
Media3 gwarantuje zgodność plików binarnych dla podzbioru powierzchni interfejsu API. Elementy, które nie gwarantują zgodności plików binarnych, są oznaczone symbolem @UnstableApi
. Aby rozróżnić to rozróżnienie, użycie niestabilnych symboli interfejsu API powoduje błąd lintowania, chyba że ma on adnotację @OptIn
.
Po migracji z ExoPlayer w wersji 2 do Media3 możesz napotkać wiele błędów lintowania interfejsu API niestabilnych. Może to sprawiać wrażenie, że Media3 jest „mniej stabilne” niż ExoPlayer v2. To nieprawda. „Niestabilne” części interfejsu Media3 API mają taki sam poziom stabilności jak cała powierzchnia interfejsu ExoPlayer v2 API, a gwarancje dotyczące stabilnej powierzchni interfejsu Media3 API nie są dostępne w ExoPlayer v2. Różnica polega na tym, że błąd lintowania informuje teraz o różnych poziomach stabilności.
Obsługa niestabilnych błędów lintowania interfejsu API
Zapoznaj się z sekcją rozwiązywania problemów z tymi błędami lintowania, aby dowiedzieć się, jak w @OptIn
dodawać adnotacje do niestabilnych interfejsów API w Javie i Kotlinie.
Wycofane interfejsy API
Możesz zauważyć, że wywołania wycofanych interfejsów API w Android Studio są przekreślone. Zalecamy zastąpienie takich połączeń odpowiednią alternatywą. Najedź kursorem na ten symbol, aby zobaczyć dokument JavaDoc informujący o tym, którego interfejsu API użyć.
Przykładowe fragmenty kodu i aplikacje demonstracyjne
- Aplikacja demonstracyjna sesji na AndroidaX Media3 (na urządzenia mobilne i Wear OS)
- Działania niestandardowe
- Powiadomienie w interfejsie systemowym, MediaButton/BT
- Sterowanie odtwarzaniem w Asystencie Google
- UAMP: Android Media Player (branch media3) (urządzenia mobilne, system AutomotiveOS)
- Powiadomienie w interfejsie systemu, MediaButton/BT, wznowienie odtwarzania
- Sterowanie odtwarzaniem w Asystencie Google/Wear OS
- AutomotiveOS: niestandardowe polecenie i logowanie