Aplikacje, które obecnie używają samodzielnej usługi com.google.android.exoplayer2
, a biblioteka androidx.media
powinna zostać przeniesiona do androidx.media3
. Używaj
skryptu migracji do przenoszenia plików kompilacji Gradle, Javy
Pliki źródłowe Kotlin i pliki układu XML z ExoPlayer
Z 2.19.1
na AndroidX Media3 1.1.1
.
Omówienie
Przed migracją zapoznaj się z sekcjami poniżej, aby dowiedzieć się więcej korzyści płynące z nowych interfejsów API i ich migracji oraz wymagania wstępne jakie powinny spełniać projekt aplikacji.
Dlaczego warto przejść na Jetpack Media3
- To nowe miejsce na ExoPlayer, natomiast
com.google.android.exoplayer2
to wycofane. - Dostęp do Player API w różnych komponentach/procesach możesz uzyskać za pomocą
MediaBrowser
/MediaController
. - Korzystaj z rozszerzonych możliwości interfejsu
MediaSession
i interfejsu APIMediaController
. - Reklamuj możliwości odtwarzania za pomocą szczegółowej kontroli dostępu.
- Uprość swoją aplikację, usuwając funkcje
MediaSessionConnector
iPlayerNotificationManager
- Zgodność wsteczna z interfejsami API klienta kompatybilnych 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 Moduł mediasession, który został wycofany. Aplikacje lub moduły w zależności od tego, pakiety wcom.google.android.exoplayer2
można przenieść za pomocą skrypt migracji. - MediaSessionConnector (w zależności od
androidx.media.*
pakietów poandroidx.media:media:1.4.3+
)
UsuńMediaSessionConnector
i użyjandroidx.media3.session.MediaSession
. - Media BrowserServiceCompat (w zależności od
androidx.media.*
pakietów poandroidx.media:media:1.4.3+
)
Przenieś podklasy klasyandroidx.media.MediaBrowserServiceCompat
doandroidx.media3.session.MediaLibraryService
i kod za pomocąMediaBrowserCompat.MediaItem
doandroidx.media3.common.MediaItem
. - Media BrowserCompat (w zależności od
android.support.v4.media.*
pakietów poandroidx.media:media:1.4.3+
)
Przeprowadź migrację kodu klienta za pomocąMediaBrowserCompat
lubMediaControllerCompat
, aby użyćandroidx.media3.session.MediaBrowser
dziękiandroidx.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 Twój projekt nie jest jeszcze kontrolowany nad źródłem, to jest dobry moment aby zacząć od niego. Jeśli z jakiegoś powodu nie chcesz tego robić, utwórz kopii zapasowej projektu przed rozpoczęciem migracji.
Aktualizowanie aplikacji
Zalecamy zaktualizowanie projektu tak, aby używał najnowszą wersję biblioteki ExoPlayer i usuń wszystkie wywołań wycofanych metod. Jeśli chcesz użyj skryptu migracji, musisz dopasować która jest obsługiwana przez skrypt.
Zwiększ parametr buildSdkVersion aplikacji do co najmniej 32.
Uaktualnij Gradle i wtyczkę Android Studio Gradle do najnowszej wersji która działa ze zaktualizowanymi zależnościami przedstawionymi powyżej. Dla: instancja:
- Wersja wtyczki Androida do obsługi Gradle: 7.1.0
- Wersja Gradle: 7.4
Zastąp wszystkie instrukcje importu symboli zastępczych, które używają asterksu (*) i użyj pełnych i jednoznacznych instrukcji importu: usuń symbol wieloznaczny importując wyciągi i za pomocą Android Studio zaimportujemy instrukcje (F2 – Alt/Enter, F2 – Alt/Enter itd.).
Migracja z usługi
com.google.android.exoplayer2.PlayerView
docom.google.android.exoplayer2.StyledPlayerView
. Jest to konieczne bo nie ma odpowiednikacom.google.android.exoplayer2.PlayerView
w AndroidX Media3.
Migracja ExoPlayer z obsługą skryptów
Skrypt ułatwia przejście z com.google.android.exoplayer2
do nowej
pakietu i modułów w sekcji androidx.media3
. Skrypt zostanie zastosowany
testy weryfikacji projektu, a w przypadku niepowodzenia – wyświetlane są ostrzeżenia.
W przeciwnym razie stosowane są mapowania zmienionych klas i pakietów w sekcji
zasobów projektu Gradle na Androida napisanego 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 w witrynie GitHub odpowiadający wersji, do której aplikacja została zaktualizowana:
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 dla migracja (aby wymusić wyświetlanie strony bez ostrzeżeń, użyj polecenia-f
):./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 .- 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 wymagań wstępnych, można przeprowadzić migrację wymuszone przez flagę
-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ąż problem.
potencjalnych problemów (rozważ zgłoszenie błędu, jeśli uważasz, że skrypt zawiera
ogólny problem, który został wprowadzony bez podania opcji
-f
). - Utwórz projekt: użyj
./gradlew clean build
lub Androida. W Studio kliknij kolejno Plik > Zsynchronizuj projekt z plikami Gradle, a następnie Kompilacja > Wyczyść projekt, a następnie Build > (Kompilacja) Przebuduj projekt (monitoruj kompilację w „Kompilacja – dane wyjściowe kompilacji” w Android Studio.
Zalecane dodatkowe czynności:
- 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. Najedź kursorem na ostrzeżenie w Android Studio i zapoznaj się z dokumentem JavaDoc wycofanego symbolu, by dowiedzieć się, którego użyć zamiast danego wywołania.
- Posortuj instrukcje importu: otwórz projekt w Android Studio, a następnie kliknij prawym przyciskiem myszy węzeł folderu pakietu w przeglądarce projektu i wybierz Zoptymalizuj importowanie pakietów, które zawierają zmienione pliki źródłowe.
Zamień MediaSessionConnector
na androidx.media3.session.MediaSession
W starszym świecie MediaSessionCompat
obiekt MediaSessionConnector
był
odpowiada za synchronizację stanu odtwarzacza ze stanem sesji
i otrzymywanie poleceń od kontrolerów, które wymagają
przekazania dostępu do odpowiednich
metod grania. W AndroidX Media3 MediaSession
robi to bezpośrednio
bez konieczności stosowania oprogramowania sprzęgającego.
Usuń wszystkie odniesienia i wykorzystanie interfejsu MediaSessionConnector: jeśli automatycznego skryptu do migracji klas i pakietów ExoPlayer, skrypt prawdopodobnie pozostawił Twój kod w stanie niemożliwym do skompilowania w odniesieniu do
MediaSessionConnector
, których nie można rozwiązać. Android Studio podczas próby skompilowania lub uruchomienia aplikacji pojawi się uszkodzony kod.W pliku
build.gradle
, w którym przechowujesz zależności, dodaj parametr zależność wdrożenia do modułu sesji AndroidX Media3 i usuń starszą zależność:implementation "androidx.media3:media3-session:1.4.0"
Zamień
MediaSessionCompat
naandroidx.media3.session.MediaSession
Na stronie kodu, w której masz utworzoną starszą wersję
MediaSessionCompat
, użyj koduandroidx.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. Nie jest to jednak wymagane. Jeśli jeśli chcesz zezwolić kontrolerom na dodawanie elementów multimedialnych do odtwarzacza,MediaSession.Callback.onAddMediaItems()
Obsługuje różne bieżące i starszych metod interfejsu API, które dodają elementy multimedialne do odtwarzacza w celu wstecznie. Obejmuje to m.in.:MediaController.set/addMediaItems()
metody kontrolera Media3, orazTransportControls.prepareFrom*/playFrom*
starszej wersji interfejsu API. Przykładowa implementacja interfejsuonAddMediaItems
może 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 wdrożone w funkcji 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 typu MediaLibraryService
i jego element nadrzędny
klasa MediaSessionService
stanowi dobre wprowadzenie do interfejsu API oraz
asynchroniczny model programowania usługi.
Aplikacja MediaLibraryService
jest zgodna wstecznie z
MediaBrowserService
Aplikacja kliencka, która używa MediaBrowserCompat
lub
MediaControllerCompat
, będzie nadal działać bez zmian w kodzie po połączeniu
do: MediaLibraryService
. Dla klienta jasne jest, czy aplikacja jest
za pomocą modelu MediaLibraryService
lub starszej wersji MediaBrowserServiceCompat
.
![Diagram komponentu aplikacji z usługą, aktywnością i aplikacjami zewnętrznymi.](https://developer.android.com/static/media/images/overview.png?authuser=0000&hl=pl)
- ,
Aby zgodność wsteczna działała, zarejestruj obie usługi z usługą w interfejsie
AndroidManifest.xml
. W ten sposób Klient znajduje 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 parametr zależność wdrożenia od modułu sesji AndroidX Media3 oraz usuń starszą zależność:implementation "androidx.media3:media3-session:1.4.0"
Zmień swoją usługę tak, aby dziedziczyła z elementu
MediaLibraryService
, a nie zMediaBrowserService
Jak wspomnieliśmy wcześniej, urządzenieMediaLibraryService
jest zgodne ze starszą wersją.MediaBrowserService
W związku z tym szerszy interfejs API, w którym dana usługa jest oferowane klientom pozostaje bez zmian. Możliwe więc, że aplikacja zachowa większość logiki wymaganej do wdrożeniaMediaBrowserService
i dostosuj ją do nowego środowiska:MediaLibraryService
.Główne różnice w porównaniu ze starszą wersją
MediaBrowserServiceCompat
są takie:Zaimplementuj metody cyklu życia usługi: metody, które muszą do zastąpienia w samej usłudze to
onCreate/onDestroy
, gdzie aplikacja przydziela/uwalnia sesję biblioteki, odtwarzacz i inne elementy i zasobami Google Cloud. Oprócz standardowych metod cyklu życia usługi aplikacja musi zastąpić wartośćonGetSession(MediaSession.ControllerInfo)
, aby zwrócićMediaLibrarySession
, który powstał wonCreate
.Implement MediaLibraryService.MediaLibrarySessionCallback: kompilacja sesja wymaga
MediaLibraryService.MediaLibrarySessionCallback
, który stosuje rzeczywiste metody API domeny. Dlatego zamiast zastępowania metod interfejsu API starszej wersji usługi, zastąpisz metodyMediaLibrarySession.Callback
.Wywołanie zwrotne jest następnie używane do utworzenia
MediaLibrarySession
:mediaLibrarySession = MediaLibrarySession.Builder(this, player, MySessionCallback()) .build()
Znajdź w nim pełny interfejs API MediaLibrarySessionCallback. dokumentacji.
Implementacja
MediaSession.Callback.onAddMediaItems()
: wywołanie zwrotne Serw:onAddMediaItems(MediaSession, ControllerInfo, List<MediaItem>)
różne obecne i starsze metody interfejsu API, które dodają elementy multimedialne do odtwarzacza. do odtwarzania w sposób zgodny wstecznie. Obejmuje to m.in.:MediaController.set/addMediaItems()
metod kontrolera Media3, orazTransportControls.prepareFrom*/playFrom*
starszej wersji interfejsu API. Przykładowa implementacja wywołania zwrotnego może znajdziesz wPlaybackService
aplikacji demonstracyjnej sesji.AndroidX Media3 korzysta z interfejsu
androidx.media3.common.MediaItem
z Media BrowserCompat.MediaItem i MediaMetadataCompat. Części kodu powiązanego ze starszymi klasami musisz odpowiednio zmienić. lub zmapuj na interfejs Media3MediaItem
.Ogólny model programowania asynchronicznego zmienił się na
Futures
w kontrastuje z podejściemResult
,MediaBrowserServiceCompat
. Implementacja usługi może zwrócić błąd asynchronicznieListenableFuture
zamiast odłączać wynik lub zwraca natychmiastową przyszłość, aby zwrócić bezpośrednio wartość.
Usunięcie PlayerPowiadomienieManagera
MediaLibraryService
automatycznie obsługuje powiadomienia o multimediach oraz
PlayerNotificationManager
można usunąć za pomocą MediaLibraryService
lub
MediaSessionService
.
Aplikacja może dostosować powiadomienie, ustawiając niestandardowe
MediaNotification.Provider
w: onCreate()
, która zastępuje
DefaultMediaNotificationProvider
. MediaLibraryService
zajmie się
uruchamianie usługi na pierwszym planie zgodnie z wymaganiami.
Dzięki zastąpieniu ustawienia MediaLibraryService.updateNotification()
aplikacja może wykonać dalsze działania
będziesz mieć uprawnienia do publikowania powiadomień oraz uruchamiania/zatrzymywania usługi w
na pierwszym planie zgodnie z wymaganiami.
Migracja kodu klienta przy użyciu przeglądarki Media Browser
W przypadku AndroidX Media3 w MediaBrowser
implementuje interfejs MediaController/Player
udostępnia interfejsy API i może być wykorzystywane do sterowania odtwarzaniem multimediów poza przeglądaniem multimediów
bibliotece. Gdyby trzeba było utworzyć atrybuty MediaBrowserCompat
i
MediaControllerCompat
, możesz zrobić to samo, używając tylko
MediaBrowser
w Media3.
Można utworzyć MediaBrowser
i poczekać na połączenie z
ustanawianie usługi:
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)
}
Zwróć uwagę na:
Sterowanie odtwarzaniem w trakcie sesji multimediów
aby dowiedzieć się, jak utworzyć klucz MediaController
do sterowania odtwarzaniem w
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 ubocznym naszego nowego rozwiązania
gwarantuje zgodność z obiektami binarnymi. Jeśli nie jest wymagany rygorystyczny kod binarny
zgodności, te błędy można bezpiecznie powstrzymać za pomocą funkcji @OptIn
adnotacja.
Tło
Ani ExoPlayer w wersji 1, ani 2 nie zapewniał ścisłych gwarancji zgodności plików binarnych dostęp do biblioteki między kolejnymi wersjami. Interfejs API ExoPlayer duży rozmiar, dzięki czemu aplikacje mogą dostosowywać niemal każdy aspekt odtwarzania. W kolejnych wersjach ExoPlayer od czasu do czasu pojawiał się symbol zmiany nazw lub inne zmiany powodujące niezgodność (np. nowe wymagane metody w interfejsach). W w większości przypadków te uszkodzenia zostały zniwelowane dzięki nowemu symbolowi oraz wycofanie starego symbolu na kilka wersji, aby umożliwić programistom czas na migrację wykorzystania, ale nie zawsze było to możliwe.
Te nieistotne zmiany spowodowały 2 problemy dla użytkowników ExoPlayer v1 oraz biblioteki w wersji 2:
- 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 średnio musi zapewnić tę samą wersję obu zależności, W przeciwnym razie niezgodności binarne mogą spowodować awarię środowiska wykonawczego.
Ulepszenia w Media3
Media3 gwarantuje zgodność plików binarnych dla podzbioru powierzchni interfejsu API.
części, które nie gwarantują zgodności binarnej, są oznaczone znakiem
@UnstableApi
. Aby wyraźnie podkreślić to rozróżnienie, zastosowania niestabilnych wersji
Symbole interfejsu API generują błąd lint, chyba że mają adnotację @OptIn
.
Po migracji z ExoPlayer v2 do Media3 możesz zauważyć wiele niestabilnych interfejsów API lintowania. Może to sprawiać wrażenie, że Media3 jest „mniej stabilne”. niż ExoPlayer wersja 2. To nieprawda. „Niestabilne” części interfejsu Media3 API są takie same poziom stabilności całej powierzchni interfejsu API ExoPlayer v2 oraz gwarancje stabilnej powierzchni interfejsu Media3 API nie są dostępne w przypadku ExoPlayer v2 na stronie wszystko. Różnica polega na tym, że błąd lintowania informuje teraz o różnych i stabilności.
Obsługa niestabilnych błędów lintowania interfejsu API
Zapoznaj się z sekcją rozwiązywania problemów z błędami lintowania, aby dowiedzieć się, jak
opisanie przypadków użycia niestabilnych interfejsów API w językach Java i Kotlin za pomocą parametru @OptIn
.
Wycofane interfejsy API
Możesz zauważyć, że wywołania wycofanych interfejsów API w Androidzie są przekreślone Studio. 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ć.
![Zrzut ekranu: jak wyświetlić dokument JavaDoc z alternatywną, wycofaną metodą](https://developer.android.com/static/media/media3/exoplayer/images/deprecation.png?authuser=0000&hl=pl)
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