A API da playlist é definida pela interface Player
, que é implementada por
todas as implementações de ExoPlayer
. As playlists permitem a reprodução sequencial de vários
itens de mídia. O exemplo a seguir mostra como iniciar a reprodução de uma playlist
contendo dois vídeos:
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();
As transições entre os itens de uma playlist são perfeitas. Não há requisito
de que eles tenham o mesmo formato. Por exemplo, não há problema em uma playlist conter
vídeos H264 e VP9. Eles podem até ser de tipos diferentes (ou seja, não há problema em uma
playlist conter streams somente de áudio e vídeos). Você pode usar o
mesmo MediaItem
várias vezes em uma playlist.
Modificar a playlist
Você pode modificar dinamicamente uma playlist adicionando, movendo, removendo ou substituindo itens de mídia. Isso pode ser feito antes e durante a reprodução, chamando os métodos correspondentes da API de playlist:
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));
Também é possível substituir e limpar toda a 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();
O player processa automaticamente as modificações durante a reprodução da maneira correta:
- Se o
MediaItem
em reprodução no momento for movido, a reprodução não será interrompida, e o novo sucessor será reproduzido após a conclusão. - Se o
MediaItem
em reprodução for removido, o player reproduzirá automaticamente o primeiro sucessor restante ou fará a transição para o estado finalizado, se não existir esse sucessor. - Se o
MediaItem
em reprodução no momento for substituído, a reprodução não será interrompida se nenhuma das propriedades naMediaItem
relevantes para a reprodução mudar. Por exemplo, é possível atualizar os camposMediaItem.MediaMetadata
na maioria dos casos sem afetar a reprodução.
Consultar a playlist
A playlist pode ser consultada usando Player.getMediaItemCount
e
Player.getMediaItemAt
. O item de mídia em reprodução pode ser consultado
chamando Player.getCurrentMediaItem
. Há também outros métodos
convenientes, como Player.hasNextMediaItem
ou Player.getNextMediaItemIndex
, para
simplificar a navegação na playlist.
Modos de repetição
O player oferece suporte a três modos de repetição que podem ser definidos a qualquer momento com
Player.setRepeatMode
:
Player.REPEAT_MODE_OFF
: a playlist não é repetida, e o player faz a transição paraPlayer.STATE_ENDED
assim que o último item da playlist for reproduzido.Player.REPEAT_MODE_ONE
: o item atual é repetido em uma repetição infinita. Métodos comoPlayer.seekToNextMediaItem
vão ignorar isso e buscar o próximo item na lista, que será repetido em um loop infinito.Player.REPEAT_MODE_ALL
: a playlist inteira é repetida em um loop infinito.
Modo de ordem aleatória
O modo de ordem aleatória pode ser ativado ou desativado a qualquer momento com
Player.setShuffleModeEnabled
. No modo de ordem aleatória, o jogador vai tocar a
playlist em uma ordem pré-computada e aleatória. Todos os itens serão reproduzidos uma vez, e
o modo de ordem aleatória também pode ser combinado com Player.REPEAT_MODE_ALL
para repetir
a mesma ordem aleatória em um loop infinito. Quando o modo de ordem aleatória está desativado,
a reprodução continua do item atual na posição original na
playlist.
Observe que os índices retornados por métodos como Player.getCurrentMediaItemIndex
sempre se referem à ordem original não aleatória. Da mesma forma, Player.seekToNextMediaItem
não reproduzirá o item em
player.getCurrentMediaItemIndex() + 1
, mas o próximo item de acordo com a
ordem aleatória. Inserir novos itens na playlist ou remover itens vai manter
a ordem aleatória atual inalterada o máximo possível.
Como definir uma ordem de embaralhamento personalizada
Por padrão, o player aceita o embaralhamento usando DefaultShuffleOrder
.
Isso pode ser personalizado fornecendo uma implementação personalizada de ordem aleatória ou
definindo uma ordem personalizada no construtor 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);
Identificar itens da playlist
Para identificar itens da playlist, MediaItem.mediaId
pode ser definido ao criar o
item:
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();
Se um app não definir explicitamente um ID de mídia para um item de mídia, a representação de string do URI será usada.
Associar dados do app a itens da playlist
Além de um código, cada item de mídia também pode ser configurado com uma tag personalizada, que pode ser qualquer objeto fornecido pelo app. Um uso das tags personalizadas é anexar metadados a cada item de mí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();
Como detectar quando a reprodução passa para outro item de mídia
Quando a reprodução muda para outro item de mídia ou começa a repetir o mesmo
item, Listener.onMediaItemTransition(MediaItem,
@MediaItemTransitionReason)
é chamado. Esse callback recebe o novo item de
mídia com um @MediaItemTransitionReason
que indica o motivo da
transição. Um caso de uso comum de onMediaItemTransition
é atualizar a
interface do app para o novo item de mí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); }
Se os metadados necessários para atualizar a IU forem anexados a cada item de mídia usando tags personalizadas, uma implementação teria esta aparência:
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); }
Como detectar quando a playlist muda
Quando um item de mídia é adicionado, removido ou movido,
Listener.onTimelineChanged(Timeline, @TimelineChangeReason)
é chamado
imediatamente com TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED
. Esse callback é
chamado mesmo quando o jogador ainda não foi preparado.
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); } }
Quando informações como a duração de um item de mídia na playlist forem
disponibilizadas, o Timeline
será atualizado e o onTimelineChanged
será chamado
com TIMELINE_CHANGE_REASON_SOURCE_UPDATE
. Outros motivos que podem causar uma
atualização da linha do tempo incluem:
- Um manifesto que é disponibilizado após a preparação de um item de mídia adaptável.
- Um manifesto que é atualizado periodicamente durante a reprodução de uma transmissão ao vivo.