Diffuser des contenus multimédias en streaming avec ExoPlayer

1. Avant de commencer

973495692ed95e42.png

Capture d'écran : application YouTube pour Android, avec ExoPlayer comme lecteur vidéo.

ExoPlayer est un lecteur multimédia au niveau de l'application, conçu à partir d'API multimédias de base dans Android. Il s'agit d'un projet Open Source utilisé par les applications Google, y compris YouTube et Google TV. ExoPlayer est extrêmement personnalisable et extensible. C'est pourquoi il convient à de nombreux cas d'utilisation avancés. Il est compatible avec divers formats multimédias, y compris des formats adaptatifs tels que DASH et SmoothStreaming.

Prérequis

  • Une certaine connaissance du développement sur Android et d'Android Studio

Objectifs de l'atelier

  • Créer une instance ExoPlayer, qui prépare et lit les contenus multimédias depuis différentes sources
  • Intégrer ExoPlayer au cycle de vie d'une activité de l'application, pour permettre le passage en arrière-plan et au premier plan, ainsi que la reprise de la lecture dans un environnement à une ou plusieurs fenêtres
  • Utiliser des MediaItem pour créer une playlist
  • Lire des flux vidéo adaptatifs, qui adaptent la qualité du contenu multimédia à la bande passante disponible
  • Enregistrer des écouteurs d'événements pour surveiller l'état de la lecture et afficher la façon dont les écouteurs peuvent être utilisés pour mesure la qualité de la lecture
  • Utiliser des composants standards de l'UI d'ExoPlayer, puis les personnaliser pour les adapter au style de votre application

Ce dont vous avez besoin

  • Vous disposez de la dernière version stable d'Android Studio et savez comment l'utiliser. Assurez-vous qu'Android Studio, le SDK Android et le plug-in Gradle sont à jour.
  • Vous devez également disposer d'un appareil Android fonctionnant sous JellyBean (4.1) ou version ultérieure (idéalement Nougat (7.1) ou version ultérieure, car il est possible d'utiliser plusieurs fenêtres avec cette version de l'OS)

2. Configuration

Obtenir le code

Pour commencer, téléchargez le projet Android Studio :

Vous pouvez également cloner le dépôt GitHub :

git clone https://github.com/googlecodelabs/exoplayer-intro.git

Structure des répertoires

Une fois le dépôt cloné ou décompressé, vous pouvez accéder au dossier racine (exoplayer-intro), qui contient un projet Gradle composé de plusieurs modules : un module d'application et un module pour chaque étape de cet atelier de programmation, avec toutes les ressources nécessaires.

Importer le projet

  1. Lancez Android Studio.
  2. Sélectionnez Fichier > Nouveau > Importer un projet*.*
  3. Sélectionnez le fichier racine build.gradle.

128162a042143d68.png

Capture d'écran : structure du projet importé

Une fois le projet compilé, six modules s'affichent : le module app (de type application) et cinq modules nommés exoplayer-codelab-N (où N correspond à un chiffre compris entre 00 et 04,, chacun de type bibliothèque). Le module app ne contient qu'un fichier manifeste. L'intégralité du module exoplayer-codelab-N spécifié fusionne lorsque l'application est compilée avec une dépendance Gradle dans app/build.gradle.

app/build.gradle

dependencies {
   implementation project(":exoplayer-codelab-00")
}

L'activité du lecteur multimédia est conservée dans le module exoplayer-codelab-N. Si elle reste stockée dans un module de bibliothèque distinct, c'est pour que vous puissiez la partager entre des APK ciblant différentes plates-formes (mobile et Android TV, par exemple). De plus, vous pouvez ainsi profiter de certaines fonctionnalités, comme Dynamic Delivery, qui permet d'installer votre fonctionnalité de lecture de contenus multimédias uniquement lorsque l'utilisateur en a besoin.

  1. Déployez et exécutez l'application pour vérifier que tout fonctionne bien. L'application doit remplir l'écran avec un arrière-plan noir.

9c330b9a6231f72a.png

Capture d'écran : application vide en cours d'exécution

3. Diffuser des contenus en streaming

Ajouter une dépendance ExoPlayer

ExoPlayer fait partie de la bibliothèque Jetpack Media3. Chaque version est identifiée de manière unique par une chaîne au format suivant :

androidx.media3:media3-exoplayer:X.X.X

Vous pouvez ajouter ExoPlayer à votre projet en important simplement ses classes et composants d'UI. Ce projet est plutôt de petite taille, avec une empreinte minime d'environ 70 à 300 ko, selon les fonctionnalités incluses et les formats pris en charge. La bibliothèque d'ExoPlayer est divisée en modules pour que les développeurs puissent importer uniquement la fonctionnalité dont ils ont besoin. Pour en savoir plus sur la structure modulaire d'ExoPlayer, reportez-vous à la section Ajouter des modules ExoPlayer.

  1. Ouvrez le fichier build.gradle du module exoplayer-codelab-00.
  2. Ajoutez les lignes ci-dessous à la section dependencies, puis synchronisez le projet.

exoplayer-codelab-00/build.gradle

def mediaVersion = "1.0.0-alpha03"
dependencies {
    [...]

    implementation "androidx.media3:media3-exoplayer:$mediaVersion"
    implementation "androidx.media3:media3-ui:$mediaVersion"
    implementation "androidx.media3:media3-exoplayer-dash:$mediaVersion"
}

Ajouter l'PlayerView element

  1. Ouvrez le fichier de ressources de mise en page activity_player.xml depuis le module exoplayer-codelab-00.
  2. Placez le curseur dans l'élément FrameLayout.
  3. Commencez à saisir <PlayerView et laissez Android Studio remplir automatiquement l'élément PlayerView.
  4. Utilisez match_parent comme valeur pour width et height.
  5. Déclarez video_view comme ID.

activity_player.xml

<androidx.media3.ui.PlayerView
   android:id="@+id/video_view"
   android:layout_width="match_parent"
   android:layout_height="match_parent"/>

Dans la suite de cet atelier, cet élément d'interface utilisateur sera appelé "vue de la vidéo".

  1. Dans PlayerActivity, vous pouvez à présent obtenir une référence pour l'arborescence de vues, créée à partir du fichier XML que vous venez de modifier.

PlayerActivity.kt

private val viewBinding by lazy(LazyThreadSafetyMode.NONE) {
    ActivityPlayerBinding.inflate(layoutInflater)
}
  1. Définissez la racine de votre arborescence de vues comme vue de contenu de votre activité. Vérifiez également que la propriété videoView est visible dans votre référence viewBinding et que son type est PlayerView.
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(viewBinding.root)
}

Créer une instance d'ExoPlayer

Pour lire un contenu multimédia en streaming, vous avez besoin d'un objet ExoPlayer. Le plus simple pour en créer un consiste à utiliser la classe ExoPlayer.Builder. Comme son nom l'indique, elle se sert du schéma de compilateur pour compiler une instance ExoPlayer.

L'instance ExoPlayer est une implémentation polyvalente pratique de l'interface Player.

Ajoutez une méthode privée initializePlayer pour créer votre instance ExoPlayer.

PlayerActivity.kt

private var player: ExoPlayer? = null
[...]
private fun initializePlayer() {
    player = ExoPlayer.Builder(this)
        .build()
        .also { exoPlayer ->
            viewBinding.videoView.player = exoPlayer
        }
}

Créez une classe ExoPlayer.Builder en utilisant votre contexte, puis appelez build pour créer votre objet ExoPlayer. Celui-ci est ensuite attribué à player, que vous devez déclarer comme champ de membre. Ensuite, utilisez la propriété modifiable viewBinding.videoView.player pour lier player à la vue correspondante.

Créer un élément multimédia

Vous avez à présent besoin de contenus à lire pour votre objet player. Pour cela, créez un MediaItem. Il existe de nombreux types d'éléments MediaItem. Pour commencer, vous allez en créer un pour un fichier MP3 sur Internet.

La façon la plus simple de créer un MediaItem consiste à utiliser MediaItem.fromUri, qui accepte l'URI d'un fichier multimédia. Ajoutez le MediaItem au player à l'aide de player.setMediaItem.

  1. Ajoutez le code suivant à initializePlayer dans le bloc also :

PlayerActivity.kt

private fun initializePlayer() {
    [...]
        .also { exoPlayer ->
            [...]
            val mediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3))
            exoPlayer.setMediaItem(mediaItem)
        }
}

Notez que la valeur de R.string.media_url_mp3 est https://storage.googleapis.com/exoplayer-test-media-0/play.mp3 dans strings.xml.

Optimiser le cycle de vie de l'activité

L'instance player peut consommer énormément de ressources, y compris pour la mémoire, le processeur, les connexions réseau et les codecs matériels. Un grand nombre de ces ressources est limité, surtout pour les codecs matériels qui ne peuvent avoir qu'une seule ressource. Il est important que vous libériez ces ressources pour les autres applications à utiliser lorsque vous ne vous en servez pas, par exemple quand votre application est mise en arrière-plan.

Autrement dit, le cycle de vie de votre lecteur doit être lié au cycle de vie de votre application. Pour cela, vous devez ignorer les quatre méthodes de PlayerActivity : onStart, onResume, onPause et onStop.

  1. Ouvrez PlayerActivity, puis cliquez sur Code menu (Menu du code) > Override methods (Ignorer les méthodes).
  2. Sélectionnez onStart, onResume, onPause et onStop.
  3. Initialisez le lecteur dans le rappel onStart ou onResume, selon le niveau d'API.

PlayerActivity.kt

public override fun onStart() {
    super.onStart()
    if (Util.SDK_INT > 23) {
        initializePlayer()
    }
}

public override fun onResume() {
    super.onResume()
    hideSystemUi()
    if ((Util.SDK_INT <= 23 || player == null)) {
        initializePlayer()
    }
}

Le niveau d'API Android 24 (et supérieur) gère plusieurs fenêtres. Comme votre application peut être visible et inactive en mode fenêtre partagée, vous devez initialiser le lecteur dans onStart. Pour les niveaux d'API Android 23 et inférieurs, vous devez patienter jusqu'à ce que vous récupériez les ressources. Vous devez donc attendre onResume pour pouvoir initialiser le lecteur.

  1. Ajoutez la méthode hideSystemUi.

PlayerActivity.kt

@SuppressLint("InlinedApi")
private fun hideSystemUi() {
    WindowCompat.setDecorFitsSystemWindows(window, false)
    WindowInsetsControllerCompat(window, viewBinding.videoView).let { controller ->
        controller.hide(WindowInsetsCompat.Type.systemBars())
        controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
    }
}

hideSystemUi est une méthode d'assistance appelée dans onResume. Cette méthode vous permet d'afficher le lecteur en plein écran.

  1. Libérez les ressources avec releasePlayer (que vous allez créer juste après) dans onPause et onStop.

PlayerActivity.kt

public override fun onPause() {
    super.onPause()
    if (Util.SDK_INT <= 23) {
        releasePlayer()
    }
}

public override fun onStop() {
    super.onStop()
    if (Util.SDK_INT > 23) {
        releasePlayer()
    }
}

Pour les niveaux d'API 23 et inférieurs, vous n'avez aucune certitude qu'onStop sera appelé. Vous devez donc libérer le lecteur dès que possible dans onPause. Pour les niveaux d'API 24 et supérieurs (qui proposent les modes Multifenêtre et Fenêtre partagée), onStop sera obligatoirement appelé. Lorsqu'elle est en pause, votre activité reste visible. Vous devez donc attendre onStop pour libérer le lecteur.

Vous devez à présent créer une méthode releasePlayer, qui libère les ressources du lecteur et le détruit.

  1. Ajoutez le code suivant à l'activité :

PlayerActivity.kt

private var playWhenReady = true
private var currentItem = 0
private var playbackPosition = 0L
[...]

private fun releasePlayer() {
    player?.let { exoPlayer ->
        playbackPosition = exoPlayer.currentPosition
        currentItem = exoPlayer.currentMediaItemIndex
        playWhenReady = exoPlayer.playWhenReady
        exoPlayer.release()
    }
    player = null
}

Avant de libérer et de détruire le lecteur, stockez les informations suivantes :

  • État de lecture/pause avec playWhenReady
  • Position actuelle de la lecture avec currentPosition
  • Index d'élément multimédia actuel utilisant currentMediaItemIndex.

Il vous suffit de fournir ces informations d'état lorsque vous initialisez le lecteur pour que l'utilisateur puisse reprendre la lecture là où il l'avait arrêtée.

Derniers préparatifs

À présent, il ne vous reste plus qu'à fournir à votre lecteur, pendant l'initialisation, les informations d'état que vous avez enregistrées dans releasePlayer.

  1. Ajoutez le code suivant à initializePlayer :

PlayerActivity.kt

private fun initializePlayer() {
    [...]
    exoPlayer.playWhenReady = playWhenReady
    exoPlayer.seekTo(currentItem, playbackPosition)
    exoPlayer.prepare()
}

Voilà ce qui se passe :

  • playWhenReady indique au lecteur s'il doit démarrer la lecture dès que toutes les ressources pour la lecture ont été acquises. Comme playWhenReady est défini sur true au départ, la lecture démarre automatiquement la première fois que l'application est lancée.
  • seekTo indique au lecteur de rechercher une certaine position dans un élément multimédia spécifique. currentItem et playbackPosition sont tous deux mis à zéro afin que la lecture démarre dès le début la première fois que l'application est lancée.
  • prepare signale au lecteur qu'il doit acquérir toutes les ressources requises pour la lecture.

Lire le fichier audio

Vous avez enfin terminé ! Lancez l'application pour lire le fichier MP3 et voir l'image intégrée.

16f18510848103d7.png

Capture d'écran : l'application lit un seul titre.

Tester le cycle de vie de l'activité

Testez si l'application fonctionne dans tous les états du cycle de vie de l'activité.

  1. Lancez une autre application et remettez votre application au premier plan. Est-ce qu'elle reprend à la bonne position ?
  2. Mettez l'application en pause et passez-la en arrière-plan, puis à nouveau au premier plan. Est-ce qu'elle est toujours en pause lorsqu'elle passe en arrière-plan ?
  3. Faites pivoter l'application. Son comportement change-t-il si vous passez du mode Portrait au mode Paysage et inversement ?

Lire une vidéo

Pour lire une vidéo, il vous suffit de remplacer l'URI de l'élément multimédia par un fichier MP4.

  1. Remplacez l'URI dans initializePlayer par R.string.media_url_mp4.
  2. Relancez l'application et testez son comportement, y compris lorsqu'elle est mise en arrière-plan alors qu'une vidéo est en cours de lecture.

PlayerActivity.kt

private fun initializePlayer() {
    [...]
    val mediaItem = MediaItem.fromUri(getString(R.string.media_url_mp4))
    [...]
}

PlayerView se charge de tout. Ici, c'est la vidéo qui est affichée en plein écran, pas l'image.

b1a45ab2c7cb818d.png

Capture d'écran : l'application lit une vidéo.

Félicitations ! Vous venez de créer une application pour diffuser un fichier multimédia sur Android en streaming et en plein écran, avec la gestion du cycle de vie, les enregistrements des états et les commandes d'interface utilisateur.

4. Créer une playlist

Votre application actuelle lit un seul fichier multimédia, mais que faire si vous voulez en lire plusieurs d'affilée ? Pour cela, vous avez besoin d'une playlist.

Vous pouvez créer une playlist en ajoutant plusieurs éléments MediaItem au player à l'aide d'addMediaItem. Cela permet d'enchaîner la lecture des fichiers de manière fluide. La mise en mémoire tampon étant gérée en arrière-plan, aucune icône de chargement ne s'affiche lorsque l'utilisateur passe d'un élément multimédia à un autre.

  1. Ajoutez le code suivant à initializePlayer :

PlayerActivity.kt

private void initializePlayer() {
    [...]
    exoPlayer.addMediaItem(mediaItem) // Existing code

    val secondMediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3))
    exoPlayer.addMediaItem(secondMediaItem)
    [...]
}

Vérifiez le comportement des commandes du lecteur. Vous pouvez utiliser les boutons d92346ced6303230.png et e9346dea9156c627.png pour parcourir la liste des éléments multimédias.

8385e35505ef5983.png

Capture d'écran : commandes de lecture, avec les boutons Précédent et Suivant

C'est plutôt pratique ! Pour en savoir plus, reportez-vous à la documentation pour les développeurs sur les éléments multimédias et les playlists, ainsi qu'à cet article sur l'API Playlist.

5. Streaming adaptatif

Le streaming adaptatif est une technique de streaming de fichiers multimédias qui consiste à adapter la qualité du flux à la bande passante réseau disponible. L'utilisateur bénéficie ainsi de la meilleure qualité possible pour sa bande passante.

Généralement, le même contenu multimédia est divisé en plusieurs titres de différentes qualités (débits et résolutions). Le lecteur choisit le titre en fonction de la bande passante réseau disponible.

Chaque titre est sectionné en fragments d'une certaine durée, généralement entre 2 et 10 secondes. Cela permet au lecteur de passer rapidement d'un titre à l'autre en fonction de l'évolution de la disponibilité de la bande passante. Le lecteur se charge ensuite d'assembler à nouveau ces fragments pour que la lecture soit fluide.

Sélection de titres adaptative

Sélectionner le titre le plus adapté à l'environnement actuel est une opération centrale du streaming adaptatif. Mettez à jour votre application pour lire des fichiers multimédias en streaming en utilisant la sélection de titres adaptative.

  1. Mettez à jour initializePlayer avec le code suivant :

PlayerActivity.kt

private fun initializePlayer() {
    val trackSelector = DefaultTrackSelector(this).apply {
        setParameters(buildUponParameters().setMaxVideoSizeSd())
    }
    player = ExoPlayer.Builder(this)
        .setTrackSelector(trackSelector)
        .build()
    [...]
}

Tout d'abord, créez un DefaultTrackSelector, qui sera chargé de sélectionner les titres dans l'élément multimédia. Ensuite, indiquez à votre trackSelector de ne sélectionner que les titres de définition standard ou inférieure. Il s'agit d'un moyen efficace d'économiser les données de l'utilisateur (au détriment de la qualité). Enfin, transférez votre trackSelector à votre compilateur pour qu'il soit utilisé lors de la compilation de l'instance ExoPlayer.

Créer un MediaItem adaptatif

DASH est un format de streaming adaptatif couramment utilisé. Pour diffuser en streaming un contenu DASH, vous devez créer un MediaItem, comme précédemment. Cependant, ici, vous devez utiliser MediaItem.Builder au lieu de fromUri,

car fromUri utilise l'extension de fichier pour déterminer le format multimédia sous-jacent. Or, l'URI DASH ne possède pas d'extension de fichier. De ce fait, nous devons fournir un type MIME d'APPLICATION_MPD pour créer le MediaItem.

  1. Mettez à jour initializePlayer comme indiqué ci-dessous :

PlayerActivity.kt

private void initializePlayer() {
    [...]

    // Replace this line...
    val mediaItem = MediaItem.fromUri(getString(R.string.media_url_mp4));

    // ... with this
     val mediaItem = MediaItem.Builder()
         .setUri(getString(R.string.media_url_dash))
         .setMimeType(MimeTypes.APPLICATION_MPD)
         .build()

    // Keep this line
    exoPlayer.setMediaItem(mediaItem)

    // Remove the following lines
    val secondMediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3))
    exoPlayer.addMediaItem(secondMediaItem)
}
  1. Redémarrez l'application et observez le fonctionnement du streaming vidéo adaptatif avec DASH. C'est plutôt simple avec ExoPlayer.

Autres formats de streaming adaptatif

HLS (MimeTypes.APPLICATION_M3U8) et SmoothStreaming (MimeTypes.APPLICATION_SS) sont d'autres formats de streaming adaptatif courants qui sont compatibles avec ExoPlayer. Pour savoir comment créer d'autres sources multimédias adaptatives, reportez-vous à l'application de démonstration ExoPlayer.

6. Écouter les événements

Lors des étapes précédentes, vous avez vu comment lire en streaming des flux multimédias progressifs et adaptatifs. ExoPlayer effectue de nombreuses opérations en arrière-plan. Par exemple :

  • Allouer la mémoire
  • Télécharger les fichiers du conteneur
  • Extraire les métadonnées du conteneur
  • Décoder les données
  • Afficher la vidéo et le texte à l'écran, et diffuser l'audio sur les enceintes

Il est parfois utile de savoir ce qu'ExoPlayer fait lors de l'exécution afin de comprendre et d'améliorer l'expérience de lecture pour vos utilisateurs.

Par exemple, vous pouvez décider de refléter les changements de l'état de lecture dans l'interface utilisateur en procédant comme suit :

  • En affichant une icône de chargement lorsque le lecteur met les données en mémoire tampon
  • En affichant le texte "À regarder ensuite" en superposition à la fin de la lecture du titre

ExoPlayer propose plusieurs interfaces d'écouteur qui fournissent des rappels pour les événements utiles. Un écouteur vous permet de consigner l'état dans lequel se trouve le lecteur.

Rester à l'écoute

  1. Créez une constante TAG en dehors de la classe PlayerActivity, que vous utiliserez par la suite pour la journalisation.

PlayerActivity.kt

private const val TAG = "PlayerActivity"
  1. Implémentez l'interface Player.Listener dans une fonction de fabrique en dehors de la classe PlayerActivity. Elle servira à vous signaler les événements importants du lecteur, y compris les erreurs et ses changements d'état.
  2. Ignorez onPlaybackStateChanged en ajoutant le code suivant :

PlayerActivity.kt

private fun playbackStateListener() = object : Player.Listener {
    override fun onPlaybackStateChanged(playbackState: Int) {
        val stateString: String = when (playbackState) {
            ExoPlayer.STATE_IDLE -> "ExoPlayer.STATE_IDLE      -"
            ExoPlayer.STATE_BUFFERING -> "ExoPlayer.STATE_BUFFERING -"
            ExoPlayer.STATE_READY -> "ExoPlayer.STATE_READY     -"
            ExoPlayer.STATE_ENDED -> "ExoPlayer.STATE_ENDED     -"
            else -> "UNKNOWN_STATE             -"
        }
        Log.d(TAG, "changed state to $stateString")
    }
}
  1. Déclarez un membre privé de type Player.Listener dans PlayerActivity.

PlayerActivity.kt

class PlayerActivity : AppCompatActivity() {
    [...]

    private val playbackStateListener: Player.Listener = playbackStateListener()
}

onPlaybackStateChanged est appelé lorsque l'état de lecture change. Le nouvel état est donné par le paramètre playbackState.

Les états du lecteur sont au nombre de quatre :

État

Description

ExoPlayer.STATE_IDLE

Le lecteur a été instancié, mais n'a pas encore été préparé.

ExoPlayer.STATE_BUFFERING

Le lecteur ne peut pas lire de fichiers depuis la position actuelle, car la quantité de données en mémoire tampon n'est pas suffisante.

ExoPlayer.STATE_READY

Le lecteur peut démarrer immédiatement la lecture depuis la position actuelle. Cela signifie qu'il commencera à lire le fichier multimédia automatiquement si la valeur de la propriété playWhenReady est définie sur true. Si cette valeur est définie sur false, le lecteur est mis en pause.

ExoPlayer.STATE_ENDED

Le lecteur a terminé de lire le fichier multimédia.

Enregistrer votre écouteur

Pour que vos rappels soient appelés, vous devez enregistrer playbackStateListener auprès du lecteur, dans initializePlayer.

  1. Enregistrez l'écouteur avant que la lecture ne soit préparée.

PlayerActivity.kt

private void initializePlayer() {
    [...]
    exoPlayer.seekTo(currentWindow, playbackPosition)
    exoPlayer.addListener(playbackStateListener)
    [...]
}

Là aussi, vous devez nettoyer le code pour éviter que des références du lecteur restent présentes et provoquent une fuite de mémoire.

  1. Supprimez l'écouteur de releasePlayer :

PlayerActivity.kt

private void releasePlayer() {
    player?.let { exoPlayer ->
        [...]
        exoPlayer.removeListener(playbackStateListener)
        exoPlayer.release()
    }
    player = null
}
  1. Ouvrez logcat et exécutez l'application.
  2. Utilisez les commandes d'interface utilisateur pour rechercher, mettre en pause et reprendre la lecture. Vous devriez voir l'état de la lecture changer dans les journaux.

Aller plus loin

ExoPlayer propose d'autres écouteurs pratiques pour comprendre l'expérience de lecture de l'utilisateur. Il existe des écouteurs pour l'audio et la vidéo, ainsi qu'un AnalyticsListener, qui contient les rappels de tous les écouteurs. Voici quelques-unes des méthodes les plus importantes :

  • La méthode onRenderedFirstFrame est appelée lorsque le premier frame d'une vidéo est rendu. Vous pouvez alors calculer combien de temps l'utilisateur a dû attendre pour qu'un contenu satisfaisant s'affiche à l'écran.
  • La méthode onDroppedVideoFrames est appelée lorsque des frames vidéo ont été perdus. Une perte de frames indique que la lecture est mauvaise et que l'expérience utilisateur est probablement médiocre.
  • La méthode onAudioUnderrun est appelée si la mémoire tampon audio est sous-utilisée. Une telle sous-utilisation peut être à l'origine de problèmes audio plus perceptibles que la perte de frames.

AnalyticsListener peut être ajouté à player avec addListener. Il existe également des méthodes équivalentes pour les écouteurs audio et vidéo.

L'interface Player.Listener inclut également le rappel onEvents, plus général, déclenché pour chaque changement d'état dans le lecteur. Cela peut être utile dans certains cas, par exemple pour répondre à plusieurs changements d'état simultanés ou pour répondre de la même manière à plusieurs changements d'état différents. Consultez la documentation de référence pour d'autres exemples d'utilisation du rappel onEvents au lieu de rappels de changement d'état individuels.

Déterminez les événements importants pour votre application et vos utilisateurs. Pour en savoir plus, consultez Écouter des événements du lecteur. C'est tout pour les lecteurs d'événements !

7. Félicitations

Félicitations ! Vous avez appris beaucoup de choses concernant l'intégration d'ExoPlayer dans votre application.

En savoir plus

Pour en savoir plus sur ExoPlayer, consultez le guide du développeur et le code source, et abonnez-vous au blog ExoPlayer.