Anwendungen, die derzeit die eigenständige Bibliothek com.google.android.exoplayer2
und androidx.media
verwenden, sollten zu androidx.media3
migriert werden. Verwenden Sie das Migrationsskript, um Gradle-Build-Dateien, Java- und Kotlin-Quelldateien sowie XML-Layoutdateien von ExoPlayer 2.19.1
zu AndroidX Media3 1.1.1
zu migrieren.
Übersicht
Lesen Sie vor der Migration in den folgenden Abschnitten mehr über die Vorteile der neuen APIs, die zu migrierenden APIs und die Voraussetzungen, die das Projekt Ihrer Anwendung erfüllen muss.
Vorteile der Migration zu Jetpack Media3
- Es ist das neue Zuhause von ExoPlayer, während
com.google.android.exoplayer2
eingestellt wurde. - Zugriff auf die Player API über Komponenten/Prozesse hinweg mit
MediaBrowser
/MediaController
. - Verwenden Sie die erweiterten Funktionen der
MediaSession
API und derMediaController
API. - Sie können Wiedergabefunktionen mit detaillierter Zugriffssteuerung bewerben.
- Vereinfache deine App, indem du
MediaSessionConnector
undPlayerNotificationManager
entfernst. - Abwärtskompatibel mit media-compat-Client-APIs (
MediaBrowserCompat
/MediaControllerCompat
/MediaMetadataCompat
)
Media APIs für die Migration zu AndroidX Media3
- ExoPlayer und seine Erweiterungen
Hierzu zählen alle Module des alten ExoPlayer-Projekts mit Ausnahme des eingestellten Moduls mediasession. Anwendungen oder Module, die von Paketen incom.google.android.exoplayer2
abhängen, können mit dem Migrationsskript migriert werden. - MediaSessionConnector (abhängig von den
androidx.media.*
-Paketen vonandroidx.media:media:1.4.3+
)
Entfernen SieMediaSessionConnector
und verwenden Sie stattdessenandroidx.media3.session.MediaSession
. - MediaBrowserServiceCompat (abhängig von den
androidx.media.*
-Paketen vonandroidx.media:media:1.4.3+
)
Migrieren Sie Unterklassen vonandroidx.media.MediaBrowserServiceCompat
zuandroidx.media3.session.MediaLibraryService
und Code mitMediaBrowserCompat.MediaItem
zuandroidx.media3.common.MediaItem
. - MediaBrowserCompat (abhängig von den
android.support.v4.media.*
-Paketen vonandroidx.media:media:1.4.3+
)
Migrieren Sie den Clientcode mitMediaBrowserCompat
oderMediaControllerCompat
, um denandroidx.media3.session.MediaBrowser
mitandroidx.media3.common.MediaItem
zu verwenden.
Voraussetzungen
Prüfen, ob Ihr Projekt der Versionsverwaltung unterliegt
Stellen Sie sicher, dass Sie Änderungen, die mit skriptbasierten Migrationstools angewendet wurden, einfach rückgängig machen können. Wenn Ihr Projekt noch nicht der Versionsverwaltung unterliegt, ist jetzt ein guter Zeitpunkt, damit zu beginnen. Wenn Sie dies aus irgendeinem Grund nicht tun möchten, erstellen Sie eine Sicherungskopie Ihres Projekts, bevor Sie mit der Migration beginnen.
App aktualisieren
Wir empfehlen, Ihr Projekt auf die neueste Version der ExoPlayer-Bibliothek zu aktualisieren und alle Aufrufe von verworfenen Methoden zu entfernen. Wenn Sie für die Migration das Skript verwenden möchten, müssen Sie die Version, auf die Sie aktualisieren, mit der Version abgleichen, die vom Skript verarbeitet wird.
Erhöhen Sie die compileSdkVersion Ihrer App auf mindestens 32.
Aktualisieren Sie Gradle und das Android Studio-Gradle-Plug-in auf eine aktuelle Version, die mit den aktualisierten Abhängigkeiten von oben funktioniert. Beispiel:
- Android-Gradle-Plug-in, Version 7.1.0
- Gradle-Version: 7.4
Ersetzen Sie alle Platzhalter-Importanweisungen, die einen Stern (*) verwenden, und verwenden Sie voll qualifizierte Importanweisungen: Löschen Sie die Platzhalter-Importanweisungen und verwenden Sie Android Studio, um die vollständig qualifizierten Anweisungen zu importieren (F2 – Alt/Eingabetaste, F2 – Alt/Eingabetaste, ...).
Migrieren Sie von
com.google.android.exoplayer2.PlayerView
zucom.google.android.exoplayer2.StyledPlayerView
. Dies ist notwendig, da es kein Äquivalent fürcom.google.android.exoplayer2.PlayerView
in AndroidX Media3 gibt.
ExoPlayer mit Skriptunterstützung migrieren
Das Skript erleichtert den Wechsel von com.google.android.exoplayer2
zur neuen Paket- und Modulstruktur unter androidx.media3
. Das Skript führt einige Validierungsprüfungen für Ihr Projekt durch und gibt Warnungen aus, wenn die Validierung fehlschlägt.
Andernfalls werden die Zuordnungen von umbenannten Klassen und Paketen in den Ressourcen eines Android-Gradle-Projekts angewendet, das in Java oder Kotlin geschrieben wurde.
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
Migrationsskript verwenden
Laden Sie das Migrationsskript aus dem Tag des ExoPlayer-Projekts auf GitHub herunter, das der Version entspricht, auf die Sie Ihre Anwendung aktualisiert haben:
curl -o media3-migration.sh \ "https://raw.githubusercontent.com/google/ExoPlayer/r2.19.1/media3-migration.sh"
Machen Sie das Skript ausführbar:
chmod 744 media3-migration.sh
Führen Sie das Skript mit
--help
aus, um mehr über die Optionen zu erfahren.Führen Sie das Skript mit
-l
aus, um die für die Migration ausgewählten Dateien aufzulisten (verwenden Sie-f
, um die Auflistung ohne Warnungen zu erzwingen):./media3-migration.sh -l -f /path/to/gradle/project/root
Führen Sie das Skript mit
-m
aus, um Pakete, Klassen und Module Media3 zuzuordnen. Wenn Sie das Skript mit der Option-m
ausführen, werden Änderungen auf die ausgewählten Dateien angewendet.- Bei Validierungsfehler stoppen, ohne Änderungen vorzunehmen
./media3-migration.sh -m /path/to/gradle/project/root
- Erzwungene Ausführung
Wenn das Skript einen Verstoß gegen die Voraussetzungen feststellt, kann die Migration mit dem Flag
-f
erzwungen werden:./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
Führen Sie nach der Ausführung des Skripts mit der Option -m
die folgenden manuellen Schritte aus:
- Prüfen, wie der Code durch das Skript geändert wurde: Verwenden Sie ein diff-Tool und beheben Sie potenzielle Probleme. Wenn Sie der Meinung sind, dass beim Skript ein allgemeines Problem aufgetreten ist, ohne die Option
-f
zu übergeben, können Sie einen Fehler melden. - Erstellen Sie das Projekt: Verwenden Sie entweder
./gradlew clean build
oder wählen Sie in Android Studio File > Sync Project with Gradle Files > Build > Clean project und dann Build > Rebuild project aus. Überwachen Sie Ihren Build auf dem Tab Build – Build Output von Android Studio.
Empfohlene weitere Schritte:
- Beheben Sie Opt-in-Fehler bei der Verwendung instabiler APIs.
- Veraltete API-Aufrufe ersetzen: Verwenden Sie die vorgeschlagene Ersatz-API. Halten Sie den Mauszeiger über die Warnung in Android Studio und sehen Sie in JavaDoc für das verworfene Symbol nach, um herauszufinden, was Sie anstelle eines bestimmten Aufrufs verwenden können.
- Importanweisungen sortieren: Öffnen Sie das Projekt in Android Studio, klicken Sie dann in der Projektanzeige mit der rechten Maustaste auf einen Paketordnerknoten und wählen Sie für die Pakete, die die geänderten Quelldateien enthalten, Importe optimieren aus.
MediaSessionConnector
durch androidx.media3.session.MediaSession
ersetzen
In der Legacy-MediaSessionCompat
-Umgebung war die MediaSessionConnector
dafür verantwortlich, den Status des Spielers mit dem Status der Sitzung zu synchronisieren und Befehle von Controllern zu empfangen, die eine Delegation an geeignete Spielermethoden erforderten. Bei AndroidX Media3 erfolgt dies über MediaSession
direkt, ohne dass ein Connector erforderlich ist.
Alle Verweise und Nutzung von MediaSessionConnector entfernen:Wenn Sie das automatisierte Skript zur Migration von ExoPlayer-Klassen und -Paketen verwendet haben, hat das Skript den Code wahrscheinlich in einem nicht kompilierbaren Status für
MediaSessionConnector
belassen, der nicht aufgelöst werden kann. In Android Studio wird der fehlerhafte Code angezeigt, wenn Sie versuchen, die App zu erstellen oder zu starten.Fügen Sie in der Datei
build.gradle
, in der Sie Ihre Abhängigkeiten verwalten, eine Implementierungsabhängigkeit zum AndroidX Media3-Sitzungsmodul hinzu und entfernen Sie die alte Abhängigkeit:implementation "androidx.media3:media3-session:1.3.1"
Ersetzen Sie
MediaSessionCompat
durchandroidx.media3.session.MediaSession
.Verwenden Sie auf der Codewebsite, auf der Sie das alte
MediaSessionCompat
erstellt haben,androidx.media3.session.MediaSession.Builder
, umMediaSession
zu erstellen. Übergeben Sie den Player, um den Session-Builder zu erstellen.val player = ExoPlayer.Builder(context).build() mediaSession = MediaSession.Builder(context, player) .setSessionCallback(MySessionCallback()) .build()
Implementieren Sie
MySessionCallback
gemäß den Anforderungen Ihrer App. Dies ist optional. Wenn Sie Controllern erlauben möchten, dem Player Medienelemente hinzuzufügen, müssen SieMediaSession.Callback.onAddMediaItems()
implementieren. Sie bietet verschiedene aktuelle und alte API-Methoden, die dem Player Medienelemente hinzufügen, damit diese abwärtskompatibel sind. Dazu gehören dieMediaController.set/addMediaItems()
-Methoden des Media3-Controllers sowie dieTransportControls.prepareFrom*/playFrom*
-Methoden der Legacy-API. Eine Beispielimplementierung vononAddMediaItems
finden Sie in derPlaybackService
der Sitzungs-Demo-App.Geben Sie die Mediensitzung an der Codewebsite frei, auf der Sie die Sitzung vor der Migration gelöscht haben:
mediaSession?.run { player.release() release() mediaSession = null }
MediaSessionConnector
-Funktion in Media3
In der folgenden Tabelle sind die Media3 APIs aufgeführt, die die zuvor in MediaSessionConnector
implementierten Funktionen übernehmen.
MediaSessionConnector | AndroidX Media3 |
---|---|
CustomActionProvider |
MediaSession.Callback.onCustomCommand()/
MediaSession.setCustomLayout() |
PlaybackPreparer |
MediaSession.Callback.onAddMediaItems()
(prepare() wird intern aufgerufen)
|
QueueNavigator |
ForwardingPlayer |
QueueEditor |
MediaSession.Callback.onAddMediaItems() |
RatingCallback |
MediaSession.Callback.onSetRating() |
PlayerNotificationManager |
DefaultMediaNotificationProvider/
MediaNotification.Provider |
MediaBrowserService
zu MediaLibraryService
migrieren
AndroidX Media3 führt MediaLibraryService
ein, das MediaBrowserServiceCompat
ersetzt. Das JavaDoc von MediaLibraryService
und die zugehörige übergeordnete Klasse MediaSessionService
bieten eine gute Einführung in die API und das asynchrone Programmiermodell des Dienstes.
MediaLibraryService
ist abwärtskompatibel mit MediaBrowserService
. Eine Clientanwendung, die MediaBrowserCompat
oder MediaControllerCompat
verwendet, funktioniert beim Herstellen einer Verbindung zu MediaLibraryService
weiterhin ohne Codeänderungen. Für einen Client ist es transparent, ob Ihre Anwendung ein MediaLibraryService
- oder ein Legacy-MediaBrowserServiceCompat
verwendet.
Damit die Abwärtskompatibilität funktioniert, müssen Sie beide Dienstschnittstellen bei Ihrem Dienst in der
AndroidManifest.xml
registrieren. So findet ein Client Ihren Dienst über die erforderliche Dienstschnittstelle:<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>
Fügen Sie in der Datei
build.gradle
, in der Sie Ihre Abhängigkeiten verwalten, eine Implementierungsabhängigkeit zum AndroidX Media3-Sitzungsmodul hinzu und entfernen Sie die alte Abhängigkeit:implementation "androidx.media3:media3-session:1.3.1"
Ändern Sie Ihren Dienst so, dass er von einer
MediaLibraryService
anstelle vonMediaBrowserService
übernommen wird. Wie bereits erwähnt, ist derMediaLibraryService
mit dem Legacy-MediaBrowserService
kompatibel. Entsprechend ist die API, die der Dienst für Kunden anbietet, immer noch dieselbe. Daher ist es wahrscheinlich, dass eine Anwendung den größten Teil der Logik beibehalten kann, die zum Implementieren vonMediaBrowserService
erforderlich ist, und sie für das neueMediaLibraryService
anpassen kann.Die Hauptunterschiede im Vergleich zum Legacy-
MediaBrowserServiceCompat
-Objekt sind:Methoden für den Dienstlebenszyklus implementieren: Die Methoden, die im Dienst selbst überschrieben werden müssen, sind
onCreate/onDestroy
. Dabei weist eine Anwendung die Bibliothekssitzung, den Player und andere Ressourcen zu bzw. frei. Zusätzlich zu den Standardmethoden für den Dienstlebenszyklus muss eine AnwendungonGetSession(MediaSession.ControllerInfo)
überschreiben, um die inonCreate
erstellteMediaLibrarySession
zurückzugeben.MediaLibraryService.MediaLibrarySessionCallback implementieren: Zum Erstellen einer Sitzung ist ein
MediaLibraryService.MediaLibrarySessionCallback
erforderlich, der die tatsächlichen API-Methoden der Domain implementiert. Statt die API-Methoden des alten Dienstes zu überschreiben, werden stattdessen die Methoden desMediaLibrarySession.Callback
überschrieben.Der Callback wird dann zum Erstellen des
MediaLibrarySession
verwendet:mediaLibrarySession = MediaLibrarySession.Builder(this, player, MySessionCallback()) .build()
Die vollständige API von MediaLibrarySessionCallback finden Sie in der API-Dokumentation.
Implementiere
MediaSession.Callback.onAddMediaItems()
: Der CallbackonAddMediaItems(MediaSession, ControllerInfo, List<MediaItem>)
verwendet verschiedene aktuelle und Legacy-API-Methoden, die dem Player Medienelemente hinzufügen, damit sie abwärtskompatibel wiedergegeben werden können. Dazu gehören dieMediaController.set/addMediaItems()
-Methoden des Media3-Controllers sowie dieTransportControls.prepareFrom*/playFrom*
-Methoden der Legacy-API. Eine Beispielimplementierung des Callbacks findest du in derPlaybackService
der Sitzungs-Demo-App.AndroidX Media3 verwendet
androidx.media3.common.MediaItem
anstelle von MediaBrowserCompat.MediaItem und MediaMetadataCompat. Teile des Codes, die mit den Legacy-Klassen verknüpft sind, müssen entsprechend geändert werden oder stattdessen dem Media3-MediaItem
zugeordnet werden.Das allgemeine asynchrone Programmiermodell wurde im Gegensatz zum abnehmbaren
Result
-Ansatz vonMediaBrowserServiceCompat
inFutures
geändert. Die Dienstimplementierung kann ein asynchronesListenableFuture
zurückgeben, anstatt ein Ergebnis zu trennen, oder ein sofortiges Future zurückgeben, um einen Wert direkt zurückzugeben.
PlayerNotificationManager entfernen
Der MediaLibraryService
unterstützt Medienbenachrichtigungen automatisch und der PlayerNotificationManager
kann entfernt werden, wenn du MediaLibraryService
oder MediaSessionService
verwendest.
Eine App kann die Benachrichtigung anpassen. Dazu wird in onCreate()
ein benutzerdefiniertes MediaNotification.Provider
festgelegt, das DefaultMediaNotificationProvider
ersetzt. MediaLibraryService
startet dann bei Bedarf den Dienst im Vordergrund.
Durch das Überschreiben von MediaLibraryService.updateNotification()
kann eine App weiterhin die volle Verantwortung dafür übernehmen, eine Benachrichtigung zu posten und den Dienst im Vordergrund nach Bedarf zu starten oder zu beenden.
Clientcode mit einem MediaBrowser migrieren
Bei AndroidX Media3 implementiert ein MediaBrowser
die MediaController/Player
-Schnittstellen und kann zur Steuerung der Medienwiedergabe neben dem Durchsuchen der Mediathek verwendet werden. Wenn Sie in der Legacy-Umgebung eine MediaBrowserCompat
und eine MediaControllerCompat
erstellen mussten, können Sie dasselbe tun, indem Sie nur die MediaBrowser
in Media3 verwenden.
Ein MediaBrowser
kann erstellt werden und warten, bis die Verbindung zum Dienst hergestellt wird:
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)
}
Informationen zum Erstellen einer MediaController
zur Steuerung der Wiedergabe im Hintergrund finden Sie unter Wiedergabe in der Mediensitzung steuern.
Weitere Schritte und Bereinigung
Instabile API-Fehler
Nach der Migration zu Media3 werden möglicherweise Lint-Fehler zu instabilen API-Nutzungen angezeigt.
Diese APIs sind sicher und die Lint-Fehler sind ein Nebenprodukt unserer neuen binären Kompatibilitätsgarantien. Wenn Sie keine strikte Binärkompatibilität benötigen, können diese Fehler mit einer @OptIn
-Annotation sicher unterdrückt werden.
Hintergrund
Weder ExoPlayer v1 noch v2 boten strikte Garantien hinsichtlich der Binärkompatibilität der Bibliothek zwischen nachfolgenden Versionen. Die ExoPlayer API-Oberfläche ist von Grund auf sehr groß, damit Apps nahezu jeden Aspekt der Wiedergabe anpassen können. In nachfolgenden Versionen von ExoPlayer wurden gelegentlich Symbolumbenennungen oder andere funktionsgefährdende Änderungen eingeführt (z.B. neue erforderliche Methoden für Schnittstellen). In den meisten Fällen wurden diese Probleme durch die Einführung des neuen Symbols und die Abschaffung des alten Symbols für einige Versionen ausgeglichen, um Entwicklern Zeit zu geben, ihre Nutzungen zu migrieren. Dies war jedoch nicht immer möglich.
Diese funktionsgefährdenden Änderungen führten zu zwei Problemen für Nutzer der ExoPlayer v1- und v2-Bibliotheken:
- Ein Upgrade von der ExoPlayer-Version kann dazu führen, dass die Kompilierung des Codes beendet wird.
- Eine App, die sowohl direkt als auch über eine Zwischenbibliothek von ExoPlayer abhängig war, musste sicherstellen, dass beide Abhängigkeiten zur selben Version waren. Andernfalls könnten binäre Inkompatibilitäten zu Laufzeitabstürzen führen.
Verbesserungen bei Media3
Media3 garantiert die binäre Kompatibilität für einen Teil der API-Oberfläche. Die Teile, die die Binärkompatibilität nicht garantieren, sind mit @UnstableApi
gekennzeichnet. Um diese Unterscheidung zu verdeutlichen, generieren instabile API-Symbole einen Lint-Fehler, sofern sie nicht mit @OptIn
gekennzeichnet sind.
Nach der Migration von ExoPlayer v2 zu Media3 werden möglicherweise viele instabile API-Lint-Fehler angezeigt. Dadurch kann der Eindruck entstehen, dass Media3 „weniger stabil“ ist als ExoPlayer v2. Das ist nicht der Fall. Die "instabilen" Teile der Media3 API haben dieselbe Stabilität wie die ganze Oberfläche der ExoPlayer v2 API. Die Garantien für die stabile Media3 API-Oberfläche sind in ExoPlayer v2 überhaupt nicht verfügbar. Der Unterschied besteht lediglich darin, dass ein Lint-Fehler Sie jetzt über die verschiedenen Stabilitätsstufen informiert.
Instabile API-Lint-Fehler verarbeiten
Weitere Informationen dazu, wie Sie die Java- und Kotlin-Verwendung von instabilen APIs mit @OptIn
annotieren, finden Sie im Abschnitt zur Fehlerbehebung zu diesen Lint-Fehlern.
Verworfene APIs
Aufrufe von verworfenen APIs sind in Android Studio durchgestrichen. Wir empfehlen, solche Aufrufe durch die entsprechende Alternative zu ersetzen. Bewegen Sie den Mauszeiger auf das Symbol, um das JavaDoc zu sehen, in dem angegeben wird, welche API stattdessen verwendet werden soll.
Codebeispiele und Demo-Apps
- AndroidX Media3-Demo-App für Sitzungen (Mobilgerät und Wear OS)
- Benutzerdefinierte Aktionen
- Benachrichtigung auf der System-Benutzeroberfläche, MediaButton/BT
- Wiedergabesteuerung mit Google Assistant
- UAMP: Android Media Player (branch media3) (Mobilgerät, AutomotiveOS)
- Benachrichtigung auf der System-UI, MediaButton/BT, Wiederaufnahme der Wiedergabe
- Wiedergabesteuerung mit Google Assistant und Wear OS
- AutomotiveOS: benutzerdefinierter Befehl und Anmeldung