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 procéder à la migration, 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 interface d'ExoPlayer, alors que
com.google.android.exoplayer2
n'est plus disponible. - Accédez à l'API Player sur l'ensemble des composants/processus avec
MediaBrowser
/MediaController
. - Utilisez les fonctionnalités étendues des API
MediaSession
etMediaController
. - Annoncez vos fonctionnalités de lecture grâce à un contrôle précis des accès.
- Simplifiez votre application en supprimant
MediaSessionConnector
etPlayerNotificationManager
. - Rétrocompatibilité avec les API clientes MediaCompat (
MediaBrowserCompat
/MediaControllerCompat
/MediaMetadataCompat
)
API Media à 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épendants des packages decom.google.android.exoplayer2
peuvent être migrés à l'aide du script de migration. - MediaSessionConnector (en fonction des packages
androidx.media.*
deandroidx.media:media:1.4.3+
)
SupprimezMediaSessionConnector
et utilisezandroidx.media3.session.MediaSession
à la place. - MediaBrowserServiceCompat (en fonction des packages
androidx.media.*
deandroidx.media:media:1.4.3+
)
Migrez les sous-classes deandroidx.media.MediaBrowserServiceCompat
versandroidx.media3.session.MediaLibraryService
et le code utilisantMediaBrowserCompat.MediaItem
versandroidx.media3.common.MediaItem
. - MediaBrowserCompat (en fonction des packages
android.support.v4.media.*
deandroidx.media:media:1.4.3+
)
Migrez le code client à l'aide deMediaBrowserCompat
ouMediaControllerCompat
pour utiliserandroidx.media3.session.MediaBrowser
avecandroidx.media3.common.MediaItem
.
Conditions préalables
S'assurer que le projet est soumis au contrôle de la source
Assurez-vous de pouvoir facilement annuler les modifications apportées par les outils de migration créés à l'aide de scripts. Si votre projet n'est pas encore soumis au contrôle de la source, le moment est venu de vous lancer. 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 afin d'utiliser la version la plus récente de la bibliothèque ExoPlayer et de supprimer tous les appels de méthodes obsolètes. Si vous avez l'intention d'utiliser le script pour la migration, vous devez faire correspondre la version vers laquelle vous effectuez la mise à jour avec la version gérée par le script.
Définissez la compileSdkVersion de votre application sur 32 au minimum.
Mettez à niveau Gradle et le plug-in Gradle d'Android Studio vers une version récente qui fonctionne avec les dépendances mises à jour ci-dessus. Par exemple:
- Plug-in Android Gradle 7.1.0
- Version de Gradle: 7.4
Remplacez toutes les instructions d'importation génériques qui utilisent un astérisque (*) et utilisez des instructions d'importation complètes: supprimez les instructions d'importation à caractère générique et utilisez Android Studio pour importer les instructions complètes (F2 - Alt/Entrée, F2 - Alt/Entrée, etc.).
Passez de
com.google.android.exoplayer2.PlayerView
àcom.google.android.exoplayer2.StyledPlayerView
. Cela est nécessaire, car il n'existe pas d'équivalent àcom.google.android.exoplayer2.PlayerView
dans AndroidX Media3.
Migrer ExoPlayer avec prise en charge des scripts
Le script facilite le passage de com.google.android.exoplayer2
au nouveau package et à la nouvelle structure de module sous androidx.media3
. Le script applique des contrôles de validation à votre projet et affiche des avertissements en cas d'échec de la validation.
Sinon, il applique les mappages de classes et de packages renommés dans les ressources d'un projet Android Gradle écrit en Java ou 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 du tag du projet ExoPlayer sur GitHub correspondant à la version vers 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 création de 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 avec 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 effectuer de modifications
./media3-migration.sh -m /path/to/gradle/project/root
- Exécution forcée
Si le script détecte un cas de non-respect des conditions préalables, la migration peut être forcée avec l'option
-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
Après avoir exécuté le script avec l'option -m
, effectuez cette procédure manuelle:
- Vérifiez comment le script a modifié votre code: utilisez un outil de comparaison des différences et corrigez les problèmes potentiels (envisagez de signaler 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), Build > Clean project (Compiler > Nettoyer le projet), puis Build > Rebuild project (Compiler > Recompiler le projet) (surveillez votre compilation dans l'onglet "Build - Build Output" d'Android Studio).
Étapes de suivi recommandées:
- Résolution de l'activation des erreurs d'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 le 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 le lecteur de projet et sélectionnez Optimize imports (Optimiser les importations) pour les packages contenant les fichiers sources modifiés.
Remplacez MediaSessionConnector
par androidx.media3.session.MediaSession
.
Dans l'ancien environnement MediaSessionCompat
, MediaSessionConnector
était chargé de synchroniser l'état du joueur avec l'état de la session et de recevoir les commandes des manettes nécessitant une délégation aux méthodes appropriées. Avec AndroidX Media3, cette opération est effectuée directement par MediaSession
, sans nécessiter de connecteur.
Supprimer toutes les références et l'utilisation de MediaSessionConnector:si vous avez utilisé le script automatisé pour migrer les classes et les packages ExoPlayer, il a probablement laissé votre code dans un état non compilable concernant
MediaSessionConnector
, qui ne peut pas être résolu. Android Studio affiche le code défaillant 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.3.1"
Remplacez
MediaSessionCompat
parandroidx.media3.session.MediaSession
.Sur le site du code sur lequel vous avez créé l'ancienne
MediaSessionCompat
, utilisezandroidx.media3.session.MediaSession.Builder
pour créer uneMediaSession
. Donnez la priorité au joueur 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 (facultatif). Si vous souhaitez autoriser les manettes à ajouter des éléments multimédias au lecteur, implémentezMediaSession.Callback.onAddMediaItems()
. Elle diffuse diverses méthodes d'API actuelles et anciennes qui ajoutent des éléments multimédias au lecteur pour une lecture avec rétrocompatibilité. 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
dans lePlaybackService
de l'application de démonstration de la session.Libérez la session multimédia sur le 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 |
ForwardingPlayer |
QueueEditor |
MediaSession.Callback.onAddMediaItems() |
RatingCallback |
MediaSession.Callback.onSetRating() |
PlayerNotificationManager |
DefaultMediaNotificationProvider/
MediaNotification.Provider |
Migrer MediaBrowserService
vers MediaLibraryService
AndroidX Media3 introduit MediaLibraryService
qui remplace MediaBrowserServiceCompat
. Le JavaDoc de MediaLibraryService
et sa super-classe MediaSessionService
fournissent 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 du code lorsqu'elle se connecte à un MediaLibraryService
. Pour un client, il est transparent que 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
AndroidManifest.xml
. De cette façon, un client trouve 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.3.1"
Modifiez votre service pour qu'il hérite d'un
MediaLibraryService
au lieu deMediaBrowserService
. Comme indiqué précédemment, leMediaLibraryService
est compatible avec l'ancienMediaBrowserService
. Par conséquent, l'API globale proposée par le service aux clients reste la même. Il est donc probable qu'une application conserve la plupart de la logique requise pour implémenterMediaBrowserService
et l'adapter au nouveauMediaLibraryService
.Les principales différences par rapport à l'ancien
MediaBrowserServiceCompat
sont les suivantes:Implémenter les méthodes du 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 de service, une application doit ignoreronGetSession(MediaSession.ControllerInfo)
pour renvoyer leMediaLibrarySession
créé dansonCreate
.Implémenter MediaLibraryService.MediaLibrarySessionCallback:la création d'une session nécessite un
MediaLibraryService.MediaLibrarySessionCallback
qui implémente les méthodes API du domaine. Ainsi, au lieu de remplacer les méthodes API de l'ancien service, vous remplacez les méthodes deMediaLibrarySession.Callback
.Le rappel est ensuite utilisé pour créer
MediaLibrarySession
:mediaLibrarySession = MediaLibrarySession.Builder(this, player, MySessionCallback()) .build()
Vous trouverez l'API complète de MediaLibrarySessionCallback dans la documentation de l'API.
Implémentation de
MediaSession.Callback.onAddMediaItems()
: le rappelonAddMediaItems(MediaSession, ControllerInfo, List<MediaItem>)
diffuse diverses méthodes d'API actuelles et anciennes qui ajoutent des éléments multimédias au lecteur pour une lecture 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 de MediaMetadataCompat. Les parties de votre code liées aux anciennes classes doivent être modifiées en conséquence ou correspondre à l'MediaItem
Media3.Le modèle de programmation asynchrone général est passé à
Futures
, contrairement à l'approcheResult
détachable deMediaBrowserServiceCompat
. L'implémentation de votre service peut renvoyer unListenableFuture
asynchrone au lieu de dissocier un résultat ou de renvoyer un Future immédiat pour renvoyer directement une valeur.
Supprimer PlayerNotificationManager
MediaLibraryService
prend automatiquement en charge les notifications multimédias 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
se charge ensuite de démarrer le service au premier plan si nécessaire.
En remplaçant MediaLibraryService.updateNotification()
, une application peut également se charger entièrement de publier une notification et de démarrer/arrêter le 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 de 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 le faire en n'utilisant que MediaBrowser
dans Media3.
Un MediaBrowser
peut être créé et attendre la connexion au service en cours d'établissement:
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 Contrôler la lecture dans la session multimédia pour découvrir comment créer un MediaController
afin de contrôler la lecture en arrière-plan.
Étapes suivantes et nettoyage
Erreurs d'API instable
Après la migration vers Media3, vous pouvez rencontrer des erreurs lint concernant des utilisations instables de l'API.
Ces API peuvent être utilisées de manière sécurisée, et les erreurs lint sont un résultat de nos nouvelles garanties de compatibilité binaire. Si vous n'avez pas besoin d'une compatibilité binaire stricte, ces erreurs peuvent être supprimées en toute sécurité avec une annotation @OptIn
.
Arrière-plan
Aucune des deux versions d'ExoPlayer v1 et ExoPlayer n'offre de garanties strictes sur la compatibilité binaire de la bibliothèque entre les versions ultérieures. La surface de l'API ExoPlayer est très grande de par sa conception, ce qui permet aux applications de personnaliser presque tous les aspects de la lecture. Les versions ultérieures d'ExoPlayer introduisent occasionnellement des noms de symboles ou d'autres modifications importantes (par exemple, de nouvelles méthodes obligatoires sur les interfaces). Dans la plupart des cas, ces failles ont été atténuées en introduisant le nouveau symbole en plus de l'abandon de l'ancien pour quelques versions, afin de laisser aux développeurs le temps de migrer leurs utilisations, mais ce n'était pas toujours possible.
Ces modifications destructives ont entraîné deux problèmes pour les utilisateurs des bibliothèques ExoPlayer v1 et v2:
- Une mise à niveau de la version d'ExoPlayer peut entraîner l'arrêt de la compilation du code.
- Une application qui dépendait d'ExoPlayer directement et via une bibliothèque intermédiaire devait s'assurer que les deux dépendances étaient la même version. Sinon, des incompatibilités binaires pouvaient entraîner des plantages au moment de l'exécution.
Améliorations apportées à Media3
Media3 garantit la compatibilité binaire pour un sous-ensemble de la surface de l'API. Les parties qui ne garantissent pas la compatibilité binaire sont marquées avec @UnstableApi
. Pour que cette distinction soit claire, les utilisations de symboles d'API instables génèrent une erreur lint, sauf s'ils sont annotés avec @OptIn
.
Après avoir migré d'ExoPlayer v2 vers Media3, vous risquez de rencontrer de nombreuses erreurs lint instables de l'API. Cela peut donner l'impression que Media3 est "moins stable" qu'ExoPlayer v2. 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. Par ailleurs, les garanties de stabilité de la surface de l'API Media3 ne sont pas du tout disponibles 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 lint instables de l'API
Vous avez deux options pour gérer les erreurs lint de l'API instable:
- Passez à l'utilisation d'une API stable qui produit le même résultat.
Continuez à utiliser l'API instable et à annoter l'utilisation avec
@OptIn
.import androidx.annotation.OptIn import androidx.media3.common.util.UnstableApi @OptIn(UnstableApi::class) fun functionUsingUnstableApi() { // Do something useful. }
Notez également qu'une annotation
kotlin.OptIn
ne doit pas être utilisée. Il est important de s'en tenir à l'annotationandroidx.annotation.OptIn
à cette fin.
Vous pouvez activer des packages entiers en ajoutant un package-info.java
:
@OptIn(markerClass = UnstableApi.class)
package name.of.your.package;
import androidx.annotation.OptIn;
import androidx.media3.common.util.UnstableApi;
Il est possible d'activer des projets entiers en supprimant l'erreur lint spécifique dans leur fichier lint.xml. Pour en savoir plus, consultez le document JavaDoc of the UnstableApi.
API obsolètes
Vous remarquerez peut-être que les appels vers des API obsolètes sont barrés dans Android Studio. Nous vous recommandons de remplacer ces appels par l'appel de remplacement approprié. Passez la souris sur le symbole pour afficher le 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 Wear OS)
- Actions personnalisées
- Notification de l'UI système, MediaButton/BT
- Commande de lecture avec l'Assistant Google
- UAMP: Android Media Player (branch media3) (mobile, AutomotiveOS)
- Notification de l'UI système, MediaButton/BT, reprise de la lecture
- Contrôle de la lecture via l'Assistant Google/Wear OS
- AutomotiveOS: commande et connexion personnalisées