Créer une application de lecteur multimédia de base avec Media3 ExoPlayer

Jetpack Media3 définit une interface Player qui décrit les fonctionnalités de base pour la lecture de fichiers audio et vidéo. ExoPlayer est l'implémentation par défaut de cette interface dans Media3. Nous vous recommandons d'utiliser ExoPlayer, car il fournit un un ensemble complet de fonctionnalités couvrant la plupart des cas d'utilisation de la lecture personnalisable pour gérer tout cas d'utilisation supplémentaire que vous pourriez avoir. ExoPlayer élimine la fragmentation de l'appareil et de l'OS afin que votre code fonctionne de manière cohérente. sur l'ensemble de l'écosystème Android. ExoPlayer inclut:

Cette page décrit certaines étapes clés de la création d'une lecture de l'application. Pour en savoir plus, vous pouvez consulter nos guides complets Media3 ExoPlayer

Premiers pas

Pour commencer, ajoutez une dépendance à ExoPlayer, à l'UI et aux modules communs de Jetpack Media3:

implementation "androidx.media3:media3-exoplayer:1.4.1"
implementation "androidx.media3:media3-ui:1.4.1"
implementation "androidx.media3:media3-common:1.4.1"

Selon votre cas d'utilisation, vous aurez peut-être aussi besoin de modules supplémentaires de Media3, comme exoplayer-dash pour lire des flux au format DASH.

Veillez à remplacer 1.4.1 par la version de votre choix bibliothèque. Consultez les notes de version pour afficher la dernière version.

Créer un lecteur multimédia

Avec Media3, vous pouvez utiliser l'implémentation incluse de Player interface standard, ExoPlayer, ou vous pouvez créer votre propre implémentation personnalisée.

Créer une instance ExoPlayer

Le moyen le plus simple de créer une instance ExoPlayer est le suivant:

Kotlin

val player = ExoPlayer.Builder(context).build()

Java

ExoPlayer player = new ExoPlayer.Builder(context).build();

Vous pouvez créer votre lecteur multimédia dans la méthode de cycle de vie onCreate() de la Activity, Fragment ou Service où il se trouve.

Le Builder inclut un éventail d'options de personnalisation qui pourraient vous intéresser, telles que:

Media3 fournit un composant d'interface utilisateur PlayerView que vous pouvez inclure dans le fichier de mise en page. Ce composant encapsule un élément PlayerControlView pour la lecture. SubtitleView pour afficher les sous-titres et Surface pour l'affichage. vidéo.

Préparer le lecteur

Ajouter des éléments multimédias à une playlist pour grâce à des méthodes telles que setMediaItem() et addMediaItem(). Appelez ensuite prepare() pour : à charger un média et à acquérir les ressources nécessaires.

N'effectuez pas ces étapes avant que l'application ne soit au premier plan. Si votre se trouve dans une Activity ou une Fragment, cela signifie qu'il doit être préparé Méthode de cycle de vie onStart() au niveau d'API 24 ou supérieur, ou onResume() au niveau d'API 23 et inférieur. Pour un joueur qui se trouve dans un Service, vous pouvez le préparer dans onCreate().

Contrôler le lecteur

Une fois le lecteur préparé, vous pouvez contrôler la lecture en appelant des méthodes sur le lecteur, par exemple:

Les composants de l'interface utilisateur tels que PlayerView ou PlayerControlView seront mis à jour en conséquence lorsqu'il est associé à un lecteur.

Relâchez le lecteur

La lecture peut nécessiter des ressources limitées, comme la vidéo des décodeurs. Il est donc important d'appeler release() sur votre lecteur pour libérer des ressources lorsqu'il n'est plus nécessaire.

Si votre lecteur se trouve dans une Activity ou une Fragment, relâchez-le dans la Méthode de cycle de vie onStop() au niveau d'API 24 ou supérieur, ou onPause() au niveau d'API 23 et inférieur. Pour un joueur associé à un Service, vous pouvez : le publier dans onDestroy().

Gérer la lecture avec une session multimédia

Sur Android, les sessions multimédias offrent une manière standardisée d'interagir avec un contenu multimédia. au-delà des limites des processus. Connecter une session multimédia à votre lecteur vous permet d'annoncer la lecture de vos contenus multimédias en externe et d'en recevoir des commandes provenant de sources externes, par exemple pour s'intégrer commandes multimédias du système sur les mobiles et les grands appareils dotés d'un écran.

Pour utiliser des sessions multimédias, ajoutez une dépendance au module de session Media3:

implementation "androidx.media3:media3-session:1.4.1"

Créer une session multimédia

Vous pouvez créer un MediaSession après avoir initialisé un lecteur comme suit:

Kotlin

val player = ExoPlayer.Builder(context).build()
val mediaSession = MediaSession.Builder(context, player).build()

Java

ExoPlayer player = new ExoPlayer.Builder(context).build();
MediaSession mediaSession = new MediaSession.Builder(context, player).build();

Media3 synchronise automatiquement l'état de Player avec l'état de MediaSession Cela fonctionne avec toutes les implémentations de Player, y compris ExoPlayer, CastPlayer ou un une implémentation personnalisée.

Accorder le contrôle à d'autres clients

Les applications clientes peuvent implémenter un contrôleur multimédia. pour contrôler la lecture de votre session multimédia. Pour recevoir ces requêtes, définissez un callback lorsque créer votre MediaSession.

Lorsqu'une manette est sur le point de se connecter à votre session multimédia, onConnect() est appelée. Vous pouvez utiliser la ControllerInfo fournie décider d'accepter ou non ou refuser la demande. Vous trouverez un exemple dans l'application de démonstration de la session Media3.

Une fois connectée, une manette peut envoyer des commandes de lecture à la session. La délègue ensuite ces commandes au joueur. Lecture et playlist définies dans l'interface Player sont automatiquement gérées par session.

D'autres méthodes de rappel vous permettent, par exemple, de gérer les requêtes pour commandes de lecture personnalisées et modifiez la playlist. Ces rappels incluent également un objet ControllerInfo. Vous pouvez donc peut déterminer le contrôle des accès à la demande.

Lecture de contenus multimédias en arrière-plan

Pour continuer à lire des contenus multimédias lorsque votre application n'est pas au premier plan, par exemple pour écouter de la musique, des livres audio ou des podcasts même si l'utilisateur n'a pas votre application ouvert, votre Player et votre MediaSession doivent être encapsulés dans un service de premier plan. Media3 fournit MediaSessionService à cette fin.

Implémenter un MediaSessionService

Créez une classe qui étend MediaSessionService et instanciez votre MediaSession dans la méthode de cycle de vie onCreate().

Kotlin

class PlaybackService : MediaSessionService() {
    private var mediaSession: MediaSession? = null

    // Create your Player and MediaSession in the onCreate lifecycle event
    override fun onCreate() {
        super.onCreate()
        val player = ExoPlayer.Builder(this).build()
        mediaSession = MediaSession.Builder(this, player).build()
    }

    // Remember to release the player and media session in onDestroy
    override fun onDestroy() {
        mediaSession?.run {
            player.release()
            release()
            mediaSession = null
        }
        super.onDestroy()
    }
}

Java

public class PlaybackService extends MediaSessionService {
    private MediaSession mediaSession = null;

    @Override
    public void onCreate() {
        super.onCreate();
        ExoPlayer player = new ExoPlayer.Builder(this).build();
        mediaSession = new MediaSession.Builder(this, player).build();
    }

    @Override
    public void onDestroy() {
        mediaSession.getPlayer().release();
        mediaSession.release();
        mediaSession = null;
        super.onDestroy();
    }
}

Dans votre fichier manifeste, votre classe Service avec un intent MediaSessionService filtrer et demander l'autorisation FOREGROUND_SERVICE pour exécuter un premier plan service:

<service
    android:name=".PlaybackService"
    android:foregroundServiceType="mediaPlayback"
    android:exported="true">
    <intent-filter>
        <action android:name="androidx.media3.session.MediaSessionService"/>
    </intent-filter>
</service>

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

Enfin, dans la classe que vous avez créée, remplacez la méthode onGetSession() pour contrôler l'accès client à votre session multimédia. Renvoyez un MediaSession pour accepter demande de connexion, ou renvoyez null pour refuser la requête.

Kotlin

// This example always accepts the connection request
override fun onGetSession(
    controllerInfo: MediaSession.ControllerInfo
): MediaSession? = mediaSession

Java

@Override
public MediaSession onGetSession(MediaSession.ControllerInfo controllerInfo) {
  // This example always accepts the connection request
  return mediaSession;
}

Se connecter à l'interface utilisateur

Maintenant que votre session multimédia se trouve dans un Service distinct de Activity ou Fragment où se trouve l'interface utilisateur de votre lecteur, vous pouvez utiliser un MediaController pour l'associer les uns aux autres. Dans la méthode onStart() de Activity ou Fragment avec votre UI, créez un SessionToken pour votre MediaSession, puis utilisez l'SessionToken pour créer un MediaController. La création d'une MediaController se produit de manière asynchrone.

Kotlin

override fun onStart() {
  val sessionToken = SessionToken(this, ComponentName(this, PlaybackService::class.java))
  val controllerFuture = MediaController.Builder(this, sessionToken).buildAsync()
  controllerFuture.addListener(
    {
        // Call controllerFuture.get() to retrieve the MediaController.
        // MediaController implements the Player interface, so it can be
        // attached to the PlayerView UI component.
        playerView.setPlayer(controllerFuture.get())
      },
    MoreExecutors.directExecutor()
  )
}

Java

@Override
public void onStart() {
  SessionToken sessionToken =
    new SessionToken(this, new ComponentName(this, PlaybackService.class));
  ListenableFuture<MediaController> controllerFuture =
    new MediaController.Builder(this, sessionToken).buildAsync();
  controllerFuture.addListener(() -> {
    // Call controllerFuture.get() to retrieve the MediaController.
    // MediaController implements the Player interface, so it can be
    // attached to the PlayerView UI component.
    playerView.setPlayer(controllerFuture.get());
  }, MoreExecutors.directExecutor())
}

MediaController implémente l'interface Player. Vous pouvez donc utiliser la même telles que play() et pause() pour contrôler la lecture. Semblable à d'autres , n'oubliez pas de libérer le MediaController lorsqu'il n'est plus nécessaire, comme la méthode de cycle de vie onStop() d'un Activity, en appelant MediaController.releaseFuture()

Publier une notification

Les services de premier plan sont requis pour publier une notification lorsqu'ils sont actifs. A MediaSessionService crée automatiquement un Notification MediaStyle pour sous la forme d'un MediaNotification. Pour fournir une notification personnalisée, créez un MediaNotification.Provider avec DefaultMediaNotificationProvider.Builder ou en créant une implémentation personnalisée de l'interface du fournisseur. Ajoutez votre à votre MediaSession avec setMediaNotificationProvider

Faire la promotion de votre bibliothèque de contenus

Un MediaLibraryService s'appuie sur un MediaSessionService en autorisant le client applications pour parcourir le contenu multimédia fourni par votre application. Les applications clientes implémentent un MediaBrowser pour interagir avec votre MediaLibraryService.

L'implémentation d'un MediaLibraryService est semblable à l'implémentation d'une MediaSessionService, sauf que dans onGetSession(), vous devez renvoyer une MediaLibrarySession au lieu d'MediaSession. Par rapport à un MediaSession.Callback, le MediaLibrarySession.Callback inclut d'autres qui permettent à un client de navigateur de parcourir le contenu proposé par votre bibliothèque.

Comme pour MediaSessionService, déclarez MediaLibraryService dans votre fichier manifeste et demander l'autorisation FOREGROUND_SERVICE pour exécuter un premier plan service:

<service
    android:name=".PlaybackService"
    android:foregroundServiceType="mediaPlayback"
    android:exported="true">
    <intent-filter>
        <action android:name="androidx.media3.session.MediaLibraryService"/>
        <action android:name="android.media.browse.MediaBrowserService"/>
    </intent-filter>
</service>

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

L'exemple ci-dessus inclut un filtre d'intent pour MediaLibraryService et, pour assurer la rétrocompatibilité, l'ancien MediaBrowserService. La Un filtre d'intent supplémentaire active les applications clientes à l'aide de l'API MediaBrowserCompat pour reconnaître votre Service.

Un MediaLibrarySession vous permet de diffuser votre bibliothèque de contenus sous forme d'arborescence. avec une seule racine MediaItem. Chaque MediaItem de l'arborescence peut avoir un nombre illimité de nœuds MediaItem enfants. Vous pouvez servir une racine différente, ou une une arborescence différente, en fonction de la requête de l'application cliente. Par exemple, l’arbre que vous à un client à la recherche d'une liste d'éléments multimédias recommandés contiennent la racine MediaItem et un seul niveau de nœuds enfants MediaItem ; tandis que l'arborescence vers laquelle vous revenez vers une autre application cliente peut représenter bibliothèque complète de contenus.

Créer un MediaLibrarySession

Un MediaLibrarySession étend l'API MediaSession pour ajouter des API de navigation de contenu. Par rapport aux Rappel MediaSession, le rappel MediaLibrarySession ajoute des méthodes telles que:

  • onGetLibraryRoot() lorsqu'un client demande la racine MediaItem d'une arborescence de contenu
  • onGetChildren() lorsqu'un client demande les enfants d'un élément MediaItem dans l'arborescence de contenu
  • onGetSearchResult() lorsqu'un client demande des résultats de recherche dans l'arborescence de contenu pour une requête

Les méthodes de rappel pertinentes incluront un LibraryParams objet avec des signaux supplémentaires sur le type d'arborescence de contenu qu'une application cliente qui vous intéresse.