Playlists

L'API de playlist est définie par l'interface Player, qui est implémentée par toutes les implémentations ExoPlayer. Les playlists permettent de lire plusieurs éléments multimédias de manière séquentielle. L'exemple suivant montre comment lancer la lecture d'une playlist contenant deux vidéos:

Kotlin

// Build the media items.
val firstItem = MediaItem.fromUri(firstVideoUri)
val secondItem = MediaItem.fromUri(secondVideoUri)
// Add the media items to be played.
player.addMediaItem(firstItem)
player.addMediaItem(secondItem)
// Prepare the player.
player.prepare()
// Start the playback.
player.play()

Java

// Build the media items.
MediaItem firstItem = MediaItem.fromUri(firstVideoUri);
MediaItem secondItem = MediaItem.fromUri(secondVideoUri);
// Add the media items to be played.
player.addMediaItem(firstItem);
player.addMediaItem(secondItem);
// Prepare the player.
player.prepare();
// Start the playback.
player.play();

Les transitions entre les éléments d'une playlist sont fluides. Il n'est pas nécessaire qu'elles soient du même format (par exemple, une playlist peut contenir à la fois des vidéos H.264 et VP9). Ils peuvent même être de différents types (c'est-à-dire qu'une playlist peut contenir des vidéos, des images et des flux audio uniquement). Vous pouvez utiliser la même MediaItem plusieurs fois dans une playlist.

Modifier la playlist

Vous pouvez modifier une playlist de manière dynamique en ajoutant, déplaçant, supprimant ou remplaçant des éléments multimédias. Vous pouvez le faire avant et pendant la lecture en appelant les méthodes d'API de playlist correspondantes:

Kotlin

// Adds a media item at position 1 in the playlist.
player.addMediaItem(/* index= */ 1, MediaItem.fromUri(thirdUri))
// Moves the third media item from position 2 to the start of the playlist.
player.moveMediaItem(/* currentIndex= */ 2, /* newIndex= */ 0)
// Removes the first item from the playlist.
player.removeMediaItem(/* index= */ 0)
// Replace the second item in the playlist.
player.replaceMediaItem(/* index= */ 1, MediaItem.fromUri(newUri))

Java

// Adds a media item at position 1 in the playlist.
player.addMediaItem(/* index= */ 1, MediaItem.fromUri(thirdUri));
// Moves the third media item from position 2 to the start of the playlist.
player.moveMediaItem(/* currentIndex= */ 2, /* newIndex= */ 0);
// Removes the first item from the playlist.
player.removeMediaItem(/* index= */ 0);
// Replace the second item in the playlist.
player.replaceMediaItem(/* index= */ 1, MediaItem.fromUri(newUri));

Vous pouvez également remplacer et effacer l'intégralité de la playlist:

Kotlin

// Replaces the playlist with a new one.
val newItems: List<MediaItem> = listOf(MediaItem.fromUri(fourthUri), MediaItem.fromUri(fifthUri))
player.setMediaItems(newItems, /* resetPosition= */ true)
// Clears the playlist. If prepared, the player transitions to the ended state.
player.clearMediaItems()

Java

// Replaces the playlist with a new one.
ImmutableList<MediaItem> newItems =
    ImmutableList.of(MediaItem.fromUri(fourthUri), MediaItem.fromUri(fifthUri));
player.setMediaItems(newItems, /* resetPosition= */ true);
// Clears the playlist. If prepared, the player transitions to the ended state.
player.clearMediaItems();

Le lecteur gère automatiquement les modifications lors de la lecture de la bonne manière:

  • Si l'MediaItem en cours de lecture est déplacé, la lecture n'est pas interrompue et son nouveau successeur est lu à la fin.
  • Si l'MediaItem en cours de lecture est supprimé, le lecteur lit automatiquement le premier successeur restant ou passe à l'état "terminé" si aucun successeur de ce type n'existe.
  • Si l'MediaItem en cours de lecture est remplacé, la lecture n'est pas interrompue si aucune des propriétés de MediaItem pertinentes pour la lecture n'a changé. Par exemple, dans la plupart des cas, vous pouvez mettre à jour les champs MediaItem.MediaMetadata sans affecter la lecture.

Interroger la playlist

La playlist peut être interrogée à l'aide de Player.getMediaItemCount et Player.getMediaItemAt. Vous pouvez interroger l'élément multimédia en cours de lecture en appelant Player.getCurrentMediaItem. Il existe également d'autres méthodes pratiques telles que Player.hasNextMediaItem ou Player.getNextMediaItemIndex pour simplifier la navigation dans la playlist.

Modes de répétition

Le lecteur accepte trois modes de répétition qui peuvent être définis à tout moment avec Player.setRepeatMode:

  • Player.REPEAT_MODE_OFF: la playlist n'est pas répétée et le lecteur passe à Player.STATE_ENDED une fois que le dernier élément de la playlist a été lu.
  • Player.REPEAT_MODE_ONE: l'élément actuel est répété en boucle infinie. Des méthodes telles que Player.seekToNextMediaItem ignoreront cela et rechercheront l'élément suivant de la liste, qui sera ensuite répété dans une boucle infinie.
  • Player.REPEAT_MODE_ALL: la playlist est répétée dans une boucle sans fin.

Mode aléatoire

Le mode aléatoire peut être activé ou désactivé à tout moment avec Player.setShuffleModeEnabled. En mode aléatoire, le lecteur lit la playlist dans un ordre précalculé et aléatoire. Tous les éléments seront lus une fois. Le mode aléatoire peut également être combiné à Player.REPEAT_MODE_ALL pour répéter la même séquence aléatoire dans une boucle infinie. Lorsque le mode aléatoire est désactivé, la lecture reprend à partir de l'élément actuel à sa position d'origine dans la playlist.

Notez que les indices renvoyés par des méthodes telles que Player.getCurrentMediaItemIndex font toujours référence à l'ordre d'origine, non mélangé. De même, Player.seekToNextMediaItem ne lit pas l'élément à player.getCurrentMediaItemIndex() + 1, mais l'élément suivant selon l'ordre de lecture aléatoire. Si vous insérez de nouveaux éléments dans la playlist ou en supprimez, l'ordre de lecture aléatoire existant reste inchangé.

Définir un ordre de lecture aléatoire personnalisé

Par défaut, le lecteur accepte la lecture en mode aléatoire à l'aide de DefaultShuffleOrder. Vous pouvez personnaliser cela en fournissant une implémentation de l'ordre de lecture aléatoire personnalisée ou en définissant un ordre personnalisé dans le constructeur DefaultShuffleOrder:

Kotlin

// Set a custom shuffle order for the 5 items currently in the playlist:
exoPlayer.setShuffleOrder(DefaultShuffleOrder(intArrayOf(3, 1, 0, 4, 2), randomSeed))
// Enable shuffle mode.
exoPlayer.shuffleModeEnabled = true

Java

// Set a custom shuffle order for the 5 items currently in the playlist:
exoPlayer.setShuffleOrder(new DefaultShuffleOrder(new int[] {3, 1, 0, 4, 2}, randomSeed));
// Enable shuffle mode.
exoPlayer.setShuffleModeEnabled(/* shuffleModeEnabled= */ true);

Identifier les éléments de la playlist

Pour identifier les éléments de la playlist, vous pouvez définir MediaItem.mediaId lors de la création de l'élément:

Kotlin

// Build a media item with a media ID.
val mediaItem = MediaItem.Builder().setUri(uri).setMediaId(mediaId).build()

Java

// Build a media item with a media ID.
MediaItem mediaItem = new MediaItem.Builder().setUri(uri).setMediaId(mediaId).build();

Si une application ne définit pas explicitement d'ID multimédia pour un élément multimédia, la représentation de chaîne de l'URI est utilisée.

Associer les données de l'application à des éléments de playlist

En plus d'un ID, chaque élément multimédia peut également être configuré avec une balise personnalisée, qui peut être n'importe quel objet fourni par l'application. Les balises personnalisées peuvent être utilisées pour associer des métadonnées à chaque élément multimédia:

Kotlin

// Build a media item with a custom tag.
val mediaItem = MediaItem.Builder().setUri(uri).setTag(metadata).build()

Java

// Build a media item with a custom tag.
MediaItem mediaItem = new MediaItem.Builder().setUri(uri).setTag(metadata).build();

Détecter quand la lecture passe à un autre élément multimédia

Lorsque la lecture passe à un autre élément multimédia ou commence à répéter le même élément multimédia, Listener.onMediaItemTransition(MediaItem, @MediaItemTransitionReason) est appelé. Ce rappel reçoit le nouvel élément multimédia, ainsi qu'un @MediaItemTransitionReason indiquant pourquoi la transition s'est produite. Un cas d'utilisation courant de onMediaItemTransition consiste à mettre à jour l'interface utilisateur de l'application pour le nouvel élément multimédia:

Kotlin

override fun onMediaItemTransition(
  mediaItem: MediaItem?,
  @MediaItemTransitionReason reason: Int,
) {
  updateUiForPlayingMediaItem(mediaItem)
}

Java

@Override
public void onMediaItemTransition(
    @Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) {
  updateUiForPlayingMediaItem(mediaItem);
}

Si les métadonnées requises pour mettre à jour l'UI sont associées à chaque élément multimédia à l'aide de balises personnalisées, une implémentation peut se présenter comme suit:

Kotlin

override fun onMediaItemTransition(
  mediaItem: MediaItem?,
  @MediaItemTransitionReason reason: Int,
) {
  var metadata: CustomMetadata? = null
  mediaItem?.localConfiguration?.let { localConfiguration ->
    metadata = localConfiguration.tag as? CustomMetadata
  }
  updateUiForPlayingMediaItem(metadata)
}

Java

@Override
public void onMediaItemTransition(
    @Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) {
  @Nullable CustomMetadata metadata = null;
  if (mediaItem != null && mediaItem.localConfiguration != null) {
    metadata = (CustomMetadata) mediaItem.localConfiguration.tag;
  }
  updateUiForPlayingMediaItem(metadata);
}

Détecter les modifications apportées à la playlist

Lorsqu'un élément multimédia est ajouté, supprimé ou déplacé, Listener.onTimelineChanged(Timeline, @TimelineChangeReason) est appelé immédiatement avec TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED. Ce rappel est appelé même lorsque le lecteur n'a pas encore été préparé.

Kotlin

override fun onTimelineChanged(timeline: Timeline, @TimelineChangeReason reason: Int) {
  if (reason == Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED) {
    // Update the UI according to the modified playlist (add, move or remove).
    updateUiForPlaylist(timeline)
  }
}

Java

@Override
public void onTimelineChanged(Timeline timeline, @TimelineChangeReason int reason) {
  if (reason == TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED) {
    // Update the UI according to the modified playlist (add, move or remove).
    updateUiForPlaylist(timeline);
  }
}

Lorsque des informations telles que la durée d'un élément multimédia de la playlist deviennent disponibles, Timeline est mis à jour et onTimelineChanged est appelé avec TIMELINE_CHANGE_REASON_SOURCE_UPDATE. La chronologie peut également être mise à jour pour d'autres raisons:

  • Fichier manifeste disponible après avoir préparé un élément multimédia adaptatif.
  • Fichier manifeste mis à jour régulièrement pendant la lecture d'une diffusion en direct.