Les applications qui utilisent actuellement la bibliothèque com.google.android.exoplayer2
autonome et androidx.media
doivent migrer vers androidx.media3
. Utilisez le script de migration pour migrer les fichiers de compilation Gradle, les fichiers sources Java et Kotlin, ainsi que les fichiers de mise en page XML d'ExoPlayer 2.19.1
vers AndroidX Media3 1.1.1
.
Présentation
Avant de migrer, consultez les sections suivantes pour en savoir plus sur les avantages des nouvelles API, les API à migrer et les conditions préalables que le projet de votre application doit remplir.
Pourquoi migrer vers Jetpack Media3 ?
- Il s'agit de la nouvelle maison d'ExoPlayer, tandis que
com.google.android.exoplayer2
est abandonné. - Accédez à l'API Player dans les composants/processus avec
MediaBrowser
/MediaController
. - Utilisez les fonctionnalités étendues de l'API
MediaSession
etMediaController
. - Annoncer les fonctionnalités de lecture avec un contrôle précis des accès
- Simplifiez votre application en supprimant
MediaSessionConnector
etPlayerNotificationManager
. - Compatibilité ascendante avec les API clientes de compatibilité multimédia (
MediaBrowserCompat
/MediaControllerCompat
/MediaMetadataCompat
)
API multimédias à migrer vers AndroidX Media3
- ExoPlayer et ses extensions
Cela inclut tous les modules de l'ancien projet ExoPlayer, à l'exception du module mediasession, qui n'est plus disponible. Les applications ou les modules dépendant des packages danscom.google.android.exoplayer2
peuvent être migrés avec le script de migration. - MediaSessionConnector (selon les packages
androidx.media.*
deandroidx.media:media:1.4.3+
)
SupprimezMediaSessionConnector
et utilisezandroidx.media3.session.MediaSession
à la place. - MediaBrowserServiceCompat (selon les packages
androidx.media.*
deandroidx.media:media:1.4.3+
)
Migrer les sous-classes deandroidx.media.MediaBrowserServiceCompat
versandroidx.media3.session.MediaLibraryService
et le code utilisantMediaBrowserCompat.MediaItem
versandroidx.media3.common.MediaItem
. - MediaBrowserCompat (selon les packages
android.support.v4.media.*
deandroidx.media:media:1.4.3+
)
Migrer le code client à l'aide deMediaBrowserCompat
ouMediaControllerCompat
pour utiliserandroidx.media3.session.MediaBrowser
avecandroidx.media3.common.MediaItem
.
Prérequis
Vérifier que votre projet est sous contrôle de version
Assurez-vous de pouvoir facilement annuler les modifications appliquées par les outils de migration par script. Si vous n'avez pas encore placé votre projet sous contrôle de version, c'est le moment idéal pour commencer. Si, pour une raison quelconque, vous ne souhaitez pas le faire, créez une copie de sauvegarde de votre projet avant de commencer la migration.
Mettre à jour votre application
Nous vous recommandons de mettre à jour votre projet pour utiliser la dernière version de la bibliothèque ExoPlayer et de supprimer tous les appels à des méthodes obsolètes. Si vous souhaitez utiliser le script pour la migration, vous devez faire correspondre la version vers laquelle vous effectuez la mise à jour à la version gérée par le script.
Augmentez la version compileSdk de votre application à au moins 32.
Mettez à niveau Gradle et le plug-in Gradle Android Studio vers une version récente compatible avec les dépendances mises à jour ci-dessus. Par exemple:
- Version du plug-in Android Gradle: 7.1.0
- Version de Gradle: 7.4
Remplacez toutes les instructions d'importation avec caractères génériques qui utilisent un astérisque (*) et utilisez des instructions d'importation entièrement qualifiées: supprimez les instructions d'importation avec caractères génériques et utilisez Android Studio pour importer les instructions entièrement qualifiées (F2 - Alt/Entrée, F2 - Alt/Entrée, etc.).
Migrer de
com.google.android.exoplayer2.PlayerView
verscom.google.android.exoplayer2.StyledPlayerView
Cela est nécessaire, car il n'existe aucun équivalent decom.google.android.exoplayer2.PlayerView
dans AndroidX Media3.
Migrer ExoPlayer avec la prise en charge des scripts
Le script facilite la transition de com.google.android.exoplayer2
vers la nouvelle structure de package et de module sous androidx.media3
. Le script applique certaines vérifications de validation à votre projet et affiche des avertissements si la validation échoue.
Sinon, il applique les mappages des classes et des packages renommés dans les ressources d'un projet Android Gradle écrit en Java ou en 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
Utiliser le script de migration
Téléchargez le script de migration à partir de la balise du projet ExoPlayer sur GitHub correspondant à la version à laquelle vous avez mis à jour votre application:
curl -o media3-migration.sh \ "https://raw.githubusercontent.com/google/ExoPlayer/r2.19.1/media3-migration.sh"
Rendez le script exécutable:
chmod 744 media3-migration.sh
Exécutez le script avec
--help
pour en savoir plus sur les options.Exécutez le script avec
-l
pour lister l'ensemble des fichiers sélectionnés pour la migration (utilisez-f
pour forcer la liste sans avertissement):./media3-migration.sh -l -f /path/to/gradle/project/root
Exécutez le script avec
-m
pour mapper les packages, les classes et les modules sur Media3. L'exécution du script avec l'option-m
applique les modifications aux fichiers sélectionnés.- Arrêter en cas d'erreur de validation sans apporter de modifications
./media3-migration.sh -m /path/to/gradle/project/root
- Exécution forcée
Si le script détecte un non-respect des conditions préalables, la migration peut être forcée avec l'indicateur
-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
Suivez ces étapes manuelles après avoir exécuté le script avec l'option -m
:
- Vérifiez comment le script a modifié votre code: utilisez un outil de comparaison et corrigez les problèmes potentiels (envoyez un bug si vous pensez que le script présente un problème général introduit sans transmettre l'option
-f
). - Compilez le projet: utilisez
./gradlew clean build
ou, dans Android Studio, sélectionnez File > Sync Project with Gradle Files (Fichier > Synchroniser le projet avec les fichiers Gradle), puis Build > Clean project (Compiler > Nettoyer le projet), puis Build > Rebuild project (Compiler > Recompiler le projet) (suivez votre compilation dans l'onglet Build - Build Output (Compilation - Sortie de compilation) d'Android Studio).
Procédure recommandée:
- Résolution des erreurs liées à l'utilisation d'API instables.
- Remplacer les appels d'API obsolètes: utilisez l'API de remplacement suggérée. Maintenez le pointeur sur l'avertissement dans Android Studio, puis consultez la documentation JavaDoc du symbole obsolète pour savoir quoi utiliser à la place d'un appel donné.
- Trier les instructions d'importation: ouvrez le projet dans Android Studio, puis effectuez un clic droit sur un nœud de dossier de package dans l'outil de visualisation du projet, puis sélectionnez Optimize imports (Optimiser les importations) sur les packages contenant les fichiers sources modifiés.
Remplacez MediaSessionConnector
par androidx.media3.session.MediaSession
.
Dans l'ancien monde MediaSessionCompat
, MediaSessionConnector
était chargé de synchroniser l'état du lecteur avec l'état de la session et de recevoir les commandes des contrôleurs qui devaient être déléguées aux méthodes de lecteur appropriées. Avec AndroidX Media3, cela est effectué directement par MediaSession
, sans nécessiter de connecteur.
Supprimez toutes les références et utilisations de MediaSessionConnector:si vous avez utilisé le script automatisé pour migrer les classes et les packages ExoPlayer, le script a probablement laissé votre code dans un état non compilable concernant les
MediaSessionConnector
qui ne peuvent pas être résolus. Android Studio affiche le code défectueux lorsque vous essayez de compiler ou de démarrer l'application.Dans le fichier
build.gradle
où vous gérez vos dépendances, ajoutez une dépendance d'implémentation au module de session AndroidX Media3 et supprimez l'ancienne dépendance:implementation "androidx.media3:media3-session:1.5.0"
Remplacez
MediaSessionCompat
parandroidx.media3.session.MediaSession
.Sur le site de code où vous avez créé l'
MediaSessionCompat
obsolète, utilisezandroidx.media3.session.MediaSession.Builder
pour générer unMediaSession
. Transmettez le lecteur pour créer le générateur de session. .val player = ExoPlayer.Builder(context).build() mediaSession = MediaSession.Builder(context, player) .setSessionCallback(MySessionCallback()) .build()
Implémentez
MySessionCallback
selon les besoins de votre application. Cette opération est facultative. Si vous souhaitez autoriser les contrôleurs à ajouter des éléments multimédias au lecteur, implémentezMediaSession.Callback.onAddMediaItems()
. Il fournit diverses méthodes d'API actuelles et anciennes qui ajoutent des éléments multimédias au lecteur pour la lecture de manière rétrocompatible. Cela inclut les méthodesMediaController.set/addMediaItems()
du contrôleur Media3, ainsi que les méthodesTransportControls.prepareFrom*/playFrom*
de l'ancienne API. Vous trouverez un exemple d'implémentation deonAddMediaItems
dansPlaybackService
de l'application de démonstration de la session.Libérez la session multimédia au niveau du site de code où vous avez détruit votre session avant la migration:
mediaSession?.run { player.release() release() mediaSession = null }
Fonctionnalité MediaSessionConnector
dans Media3
Le tableau suivant présente les API Media3 qui gèrent les fonctionnalités précédemment implémentées dans MediaSessionConnector
.
MediaSessionConnector | AndroidX Media3 |
---|---|
CustomActionProvider |
MediaSession.Callback.onCustomCommand()/
MediaSession.setCustomLayout() |
PlaybackPreparer |
MediaSession.Callback.onAddMediaItems() (prepare() est appelé en interne)
|
QueueNavigator |
ForwardingSimpleBasePlayer |
QueueEditor |
MediaSession.Callback.onAddMediaItems() |
RatingCallback |
MediaSession.Callback.onSetRating() |
PlayerNotificationManager |
DefaultMediaNotificationProvider/
MediaNotification.Provider |
Migrer MediaBrowserService
vers MediaLibraryService
AndroidX Media3 introduit MediaLibraryService
, qui remplace MediaBrowserServiceCompat
. La documentation JavaDoc de MediaLibraryService
et de sa super-classe MediaSessionService
fournit une bonne introduction à l'API et au modèle de programmation asynchrone du service.
MediaLibraryService
est rétrocompatible avec MediaBrowserService
. Une application cliente qui utilise MediaBrowserCompat
ou MediaControllerCompat
continue de fonctionner sans modification de code lors de la connexion à un MediaLibraryService
. Pour un client, il est transparent si votre application utilise un MediaLibraryService
ou un ancien MediaBrowserServiceCompat
.
Pour que la rétrocompatibilité fonctionne, vous devez enregistrer les deux interfaces de service avec votre service dans le
AndroidManifest.xml
. Un client peut ainsi trouver votre service via l'interface de service requise:<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>
Dans le fichier
build.gradle
où vous gérez vos dépendances, ajoutez une dépendance d'implémentation au module de session AndroidX Media3 et supprimez l'ancienne dépendance:implementation "androidx.media3:media3-session:1.5.0"
Modifiez votre service pour qu'il hérite d'un
MediaLibraryService
au lieu deMediaBrowserService
. Comme indiqué précédemment,MediaLibraryService
est compatible avec l'ancienMediaBrowserService
. Par conséquent, l'API plus large que le service propose aux clients reste la même. Il est donc probable qu'une application puisse conserver la majeure partie de la logique requise pour implémenterMediaBrowserService
et l'adapter au nouveauMediaLibraryService
.Les principales différences par rapport à l'ancienne
MediaBrowserServiceCompat
sont les suivantes:Implémentez les méthodes de cycle de vie du service:les méthodes qui doivent être remplacées sur le service lui-même sont
onCreate/onDestroy
, où une application alloue/libère la session de bibliothèque, le lecteur et d'autres ressources. En plus des méthodes standards du cycle de vie des services, une application doit remplaceronGetSession(MediaSession.ControllerInfo)
pour renvoyer leMediaLibrarySession
créé dansonCreate
.Implémentez MediaLibraryService.MediaLibrarySessionCallback:la création d'une session nécessite un
MediaLibraryService.MediaLibrarySessionCallback
qui implémente les méthodes d'API de domaine réelles. Ainsi, au lieu de remplacer les méthodes d'API de l'ancien service, vous remplacerez les méthodes deMediaLibrarySession.Callback
.Le rappel est ensuite utilisé pour créer le
MediaLibrarySession
:mediaLibrarySession = MediaLibrarySession.Builder(this, player, MySessionCallback()) .build()
Consultez l'API complète de MediaLibrarySessionCallback dans la documentation de l'API.
Implémenter
MediaSession.Callback.onAddMediaItems()
: le rappelonAddMediaItems(MediaSession, ControllerInfo, List<MediaItem>)
sert diverses méthodes d'API actuelles et anciennes qui ajoutent des éléments multimédias au lecteur pour la lecture de manière rétrocompatible. Cela inclut les méthodesMediaController.set/addMediaItems()
du contrôleur Media3, ainsi que les méthodesTransportControls.prepareFrom*/playFrom*
de l'ancienne API. Vous trouverez un exemple d'implémentation du rappel dans lePlaybackService
de l'application de démonstration de la session.AndroidX Media3 utilise
androidx.media3.common.MediaItem
au lieu de MediaBrowserCompat.MediaItem et MediaMetadataCompat. Les parties de votre code associées aux anciennes classes doivent être modifiées en conséquence ou mappées à laMediaItem
Media3 à la place.Le modèle de programmation asynchrone général a été remplacé par
Futures
, contrairement à l'approcheResult
amovible deMediaBrowserServiceCompat
. L'implémentation de votre service peut renvoyer unListenableFuture
asynchrone au lieu de dissocier un résultat ou renvoyer un Future immédiat pour renvoyer directement une valeur.
Supprimer PlayerNotificationManager
MediaLibraryService
est compatible avec les notifications multimédias automatiquement et PlayerNotificationManager
peut être supprimé lorsque vous utilisez MediaLibraryService
ou MediaSessionService
.
Une application peut personnaliser la notification en définissant un MediaNotification.Provider
personnalisé dans onCreate()
qui remplace le DefaultMediaNotificationProvider
. MediaLibraryService
s'occupe ensuite de démarrer le service au premier plan si nécessaire.
En remplaçant MediaLibraryService.updateNotification()
, une application peut prendre en charge l'affichage d'une notification et le démarrage/arrêt du service au premier plan, si nécessaire.
Migrer le code client à l'aide d'un MediaBrowser
Avec AndroidX Media3, un MediaBrowser
implémente les interfaces MediaController/Player
et peut être utilisé pour contrôler la lecture des contenus multimédias en plus de parcourir la bibliothèque multimédia. Si vous deviez créer un MediaBrowserCompat
et un MediaControllerCompat
dans l'ancien monde, vous pouvez faire de même en n'utilisant que le MediaBrowser
dans Media3.
Un MediaBrowser
peut être créé et attendre que la connexion au service soit établie:
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)
}
Consultez la section Contrôler la lecture dans la session multimédia pour découvrir comment créer un MediaController
permettant de contrôler la lecture en arrière-plan.
Étapes suivantes et nettoyage
Erreurs d'API instables
Après avoir migré vers Media3, vous pouvez voir des erreurs de lint concernant des utilisations instables des API.
Ces API sont sûres à utiliser, et les erreurs de lint sont un sous-produit de nos nouvelles garanties de compatibilité binaire. Si vous n'exigez pas une compatibilité binaire stricte, vous pouvez supprimer ces erreurs en toute sécurité à l'aide d'une annotation @OptIn
.
Arrière-plan
Ni la version 1 ni la version 2 d'ExoPlayer ne fournissaient de garanties strictes concernant la compatibilité binaire de la bibliothèque entre les versions ultérieures. La surface de l'API ExoPlayer est très vaste par conception, afin de permettre aux applications de personnaliser presque tous les aspects de la lecture. Les versions ultérieures d'ExoPlayer introduisaient parfois des renommages de symboles ou d'autres modifications non rétrocompatibles (par exemple, de nouvelles méthodes requises sur les interfaces). Dans la plupart des cas, ces erreurs ont été atténuées en introduisant le nouveau symbole et en abandonnant l'ancien symbole pendant quelques versions, afin de laisser aux développeurs le temps de migrer leurs utilisations. Toutefois, cela n'a pas toujours été possible.
Ces modifications incompatibles ont entraîné deux problèmes pour les utilisateurs des bibliothèques ExoPlayer v1 et v2:
- Une mise à niveau vers la version d'ExoPlayer peut entraîner l'arrêt de la compilation du code.
- Une application qui dépendait d'ExoPlayer à la fois directement et via une bibliothèque intermédiaire devait s'assurer que les deux dépendances étaient de la même version, sinon des incompatibilités binaires pouvaient entraîner des plantages d'exécution.
Améliorations apportées à Media3
Media3 garantit la compatibilité binaire pour un sous-ensemble de la surface de l'API. Les éléments qui ne garantissent pas la compatibilité binaire sont marqués avec @UnstableApi
. Pour clarifier cette distinction, les utilisations de symboles d'API instables génèrent une erreur lint, sauf si elles sont annotées avec @OptIn
.
Après avoir migré d'ExoPlayer v2 vers Media3, vous pouvez voir de nombreuses erreurs d'analyse lint instables de l'API. Cela peut donner l'impression que Media3 est "moins stable" que la version 2 d'ExoPlayer. Ce n'est pas le cas. Les parties "instables" de l'API Media3 ont le même niveau de stabilité que l'ensemble de la surface de l'API ExoPlayer v2, et les garanties de la surface de l'API Media3 stable ne sont pas disponibles du tout dans ExoPlayer v2. La différence est simplement qu'une erreur lint vous avertit désormais des différents niveaux de stabilité.
Gérer les erreurs d'analyse lint instables de l'API
Consultez la section de dépannage concernant ces erreurs lint pour savoir comment annoter les utilisations Java et Kotlin d'API instables avec @OptIn
.
API obsolètes
Vous remarquerez peut-être que les appels d'API obsolètes sont barrés dans Android Studio. Nous vous recommandons de remplacer ces appels par l'alternative appropriée. Pointez sur le symbole pour afficher la documentation JavaDoc indiquant l'API à utiliser à la place.
Exemples de code et applications de démonstration
- Application de démonstration de la session AndroidX Media3 (mobile et WearOS)
- Actions personnalisées
- Notification de l'UI système, bouton multimédia/Bluetooth
- Commandes de lecture de l'Assistant Google
- UAMP: Android Media Player (branche media3) (mobile, AutomotiveOS)
- Notification de l'UI système, bouton multimédia/Bluetooth, reprise de la lecture
- Commandes de lecture de l'Assistant Google/Wear OS
- AutomotiveOS: commande et connexion personnalisées