Esta página descreve como criar um DefaultPreloadManager, que pré-carrega
conteúdo de mídia para seu app com base na estratégia escolhida.
Os gerenciadores de pré-carregamento baseados na classe abstrata BasePreloadManager permitem classificar o conteúdo pelos critérios que você escolher. Este documento explica como usar a classe derivada DefaultPreloadManager, em que cada item de mídia é classificado com um número inteiro que representa a posição dele em uma lista (por exemplo, a posição em um carrossel de vídeos). O gerenciador de pré-carregamento prioriza o carregamento dos itens com base na proximidade do item que o usuário está reproduzindo. Assim, se um usuário passar para outro item, ele poderá começar a tocar imediatamente.
Há três etapas para criar uma instância de DefaultPreloadManager:
- Defina um
TargetPreloadStatusControlque o gerenciador de pré-carregamento possa consultar para descobrir se o item de mídia está pronto para ser carregado e quanto carregar. - Crie o builder que será usado para criar o gerenciador de pré-carregamento e
os objetos
ExoPlayerdo app. - Use o builder para criar o gerenciador de pré-carregamento chamando o método
build()do builder.
Criar um controle de status de pré-carregamento de destino
Ao criar o DefaultPreloadManager.Builder, você vai transmitir um
objeto controle de status de pré-carregamento de destino que você define. Esse objeto implementa a interface TargetPreloadStatusControl. Quando o gerenciador de pré-carregamento está
se preparando para pré-carregar mídia, ele chama o método
getTargetPreloadStatus() do controle de status para determinar se deve preparar, carregar
ou armazenar em cache o conteúdo de um item de mídia. O carregamento prévio carrega dados de mídia diretamente no buffer na memória de um player, preparando-o para reprodução instantânea, enquanto o armazenamento em cache salva os dados de mídia em um cache de disco persistente para economizar memória do player. O controle de status pode responder com um destes códigos de status:
STAGE_SPECIFIED_RANGE_LOADED: o gerenciador de pré-carregamento precisa carregar o conteúdo da posição inicial especificada e pela duração especificada (em milissegundos) no buffer na memória do player.STAGE_SPECIFIED_RANGE_CACHED: o gerenciador de pré-carregamento precisa armazenar em cache o conteúdo da posição inicial especificada e pela duração especificada (em milissegundos) no cache em disco.STAGE_TRACKS_SELECTED: o gerenciador de pré-carregamento precisa carregar e processar as informações da faixa de conteúdo e selecionar as faixas. O gerenciador de pré-carregamento ainda não deve começar a carregar o conteúdo.STAGE_SOURCE_PREPARED: o gerenciador de pré-carregamento precisa preparar a fonte de conteúdo. Por exemplo, se os metadados do conteúdo estiverem em um arquivo de manifesto separado, o gerenciador de pré-carregamento poderá buscar e analisar esse manifesto.null: o gerenciador de pré-carregamento não deve carregar conteúdo nem metadados para esse item de mídia.
Você precisa ter uma estratégia para decidir quanto conteúdo carregar para cada item de mídia. Neste exemplo, mais conteúdo é carregado para os itens mais próximos do item que está sendo reproduzido. Se o usuário estiver reproduzindo conteúdo com o índice n, o controlador vai retornar os seguintes códigos:
- Índice n+1 (o próximo item de mídia): carregue 3.000 ms (3 segundos) da posição inicial padrão.
- Índice n-1 (o item de mídia anterior): carregue 1.000 ms (1 segundo) da posição inicial padrão.
- Outros itens de mídia no intervalo n-2 a n+2: retorne
PreloadStatus.TRACKS_SELECTED - Outros itens de mídia no intervalo n-4 a n+4: retorne
PreloadStatus.SOURCE_PREPARED - Para todos os outros itens de mídia, retorne
null
class MyTargetPreloadStatusControl(var currentPlayingIndex: Int = 0) : TargetPreloadStatusControl<Int, DefaultPreloadManager.PreloadStatus> { override fun getTargetPreloadStatus(index: Int): DefaultPreloadManager.PreloadStatus { if (index - currentPlayingIndex == 1) { // next track // return a PreloadStatus that is labelled by STAGE_SPECIFIED_RANGE_LOADED and // suggest loading 3000ms from the default start position return DefaultPreloadManager.PreloadStatus.specifiedRangeLoaded(3000L) } else if (index - currentPlayingIndex == -1) { // previous track // return a PreloadStatus that is labelled by STAGE_SPECIFIED_RANGE_LOADED and // suggest loading 3000ms from the default start position return DefaultPreloadManager.PreloadStatus.specifiedRangeLoaded(3000L) } else if (abs(index - currentPlayingIndex) == 2) { // return a PreloadStatus that is labelled by STAGE_TRACKS_SELECTED return DefaultPreloadManager.PreloadStatus.PRELOAD_STATUS_TRACKS_SELECTED } else if (abs(index - currentPlayingIndex) <= 4) { // return a PreloadStatus that is labelled by STAGE_SOURCE_PREPARED return DefaultPreloadManager.PreloadStatus.PRELOAD_STATUS_SOURCE_PREPARED } return DefaultPreloadManager.PreloadStatus.PRELOAD_STATUS_NOT_PRELOADED } }
Pontos principais sobre o código
- Você vai transmitir uma instância de
MyTargetPreloadStatusControlao builder do gerenciador de pré-carregamento ao criá-lo. currentPlayingIndexcontém o índice do item de mídia que está sendo reproduzido no momento. É responsabilidade do app manter esse valor atualizado.- Quando o gerenciador de pré-carregamento está pronto para carregar conteúdo, ele chama
getTargetPreloadStatuse transmite as informações de classificação especificadas para o item de mídia correspondente. No caso deDefaultPreloadManager, essas informações de classificação são um número inteiro, especificando a posição do item em um carrossel. O método escolhe qual código retornar comparando esse índice com o índice do item selecionado no momento.
Criar o gerenciador de pré-carregamento
Para criar seu gerenciador de pré-carregamento, você precisa de um DefaultPreloadManager.Builder.
Esse builder é configurado com o contexto atual e o controle de status de pré-carregamento
de destino do app. É possível criar um gerenciador de pré-carregamento com todas as configurações
padrão.
val targetPreloadStatusControl = MyTargetPreloadStatusControl() val preloadManagerBuilder = DefaultPreloadManager.Builder(context, targetPreloadStatusControl) val preloadManager = preloadManagerBuilder.build()
O criador também fornece métodos setter que podem ser usados para definir os componentes personalizados do gerenciador de pré-carregamento.
Por exemplo, é possível personalizar o total de bytes do buffer de destino para todas as fontes de mídia de pré-carregamento em DefaultPreloadManager, para que os dados pré-carregados não excedam esse limite. É possível configurar esse limite usando
setPlayerTargetBufferBytes(String, int)
em um DefaultLoadControl.Builder personalizado com o nome do jogador "preload" e
transmitir essa instância para o builder do gerenciador de pré-carregamento:
val targetPreloadStatusControl = MyTargetPreloadStatusControl() val preloadManagerBuilder = DefaultPreloadManager.Builder(context, targetPreloadStatusControl) preloadManagerBuilder.setLoadControl( DefaultLoadControl.Builder() .setPlayerTargetBufferBytes("preload", 128 * 1024 * 1024) // 128 MiB .build() ) val preloadManager = preloadManagerBuilder.build()
Embora os métodos setter do builder sejam basicamente opcionais para
personalização, se você quiser armazenar em cache itens de mídia
no disco, configure o builder com um Cache chamando
setCache(). Se nenhum cache for configurado, tentar armazenar em cache os itens de mídia
vai resultar em um IllegalStateException.
Criar o ExoPlayer para reproduzir o item de mídia pré-carregado
Além de usar o builder para criar o gerenciador de pré-carregamento, você também o usará para
criar os objetos ExoPlayer que seu app usa para reproduzir o conteúdo, para que
o ExoPlayer compartilhe corretamente os componentes com o gerenciador de pré-carregamento. Você ainda pode definir as configurações específicas de reprodução para o ExoPlayer transmitindo uma instância ExoPlayer.Builder com essas configurações definidas.
// Direct creation val exoPlayer = preloadManagerBuilder.buildExoPlayer() // Creation with custom playback specific configurations val skipSilenceExoPlayerBuilder = ExoPlayer.Builder(context).setSkipSilenceEnabled(true) val skipSilenceExoPlayer = preloadManagerBuilder.buildExoPlayer(skipSilenceExoPlayerBuilder)