O ExoPlayer é usado com frequência para streaming de mídia pela Internet. Ele oferece suporte múltiplas pilhas de rede para fazer as solicitações de rede subjacentes. Você escolhe da pilha de rede pode ter um impacto significativo no desempenho do streaming.
Esta página descreve como configurar o ExoPlayer para usar sua pilha de rede de escolha, lista as opções disponíveis, fornece orientações sobre como escolher uma pilha de rede para seu aplicativo e explica como ativar o armazenamento em cache para mídia.
Como configurar o ExoPlayer para usar uma pilha de rede específica
O ExoPlayer carrega dados usando componentes DataSource
, que ele extrai dos
Instâncias de DataSource.Factory
injetadas pelo código do app.
Caso seu app só precise reproduzir conteúdo http(s), selecione uma rede
é tão simples quanto atualizar as instâncias DataSource.Factory
que sua
que o app injeta para ser instâncias do HttpDataSource.Factory
.
correspondente à pilha de rede que você quer usar. Se o seu app também
precisar reproduzir conteúdo que não seja HTTP(s), como arquivos locais, use
DefaultDataSource.Factory
:
Kotlin
DefaultDataSource.Factory( ... /* baseDataSourceFactory= */ PreferredHttpDataSource.Factory(...))
Java
new DefaultDataSource.Factory( ... /* baseDataSourceFactory= */ new PreferredHttpDataSource.Factory(...));
Nesse exemplo, PreferredHttpDataSource.Factory
é a fábrica correspondente ao
a pilha de rede preferencial. A camada DefaultDataSource.Factory
adiciona suporte
para fontes não HTTP(s), como arquivos locais.
O exemplo abaixo mostra como criar uma ExoPlayer
que usará a Cronet
pilha de rede e também suporta a reprodução de conteúdo não HTTP(s).
Kotlin
// Given a CronetEngine and Executor, build a CronetDataSource.Factory. val cronetDataSourceFactory = CronetDataSource.Factory(cronetEngine, executor) // Wrap the CronetDataSource.Factory in a DefaultDataSource.Factory, which adds // in support for requesting data from other sources (such as files, resources, // etc). val dataSourceFactory = DefaultDataSource.Factory(context, /* baseDataSourceFactory= */ cronetDataSourceFactory) // Inject the DefaultDataSource.Factory when creating the player. val player = ExoPlayer.Builder(context) .setMediaSourceFactory( DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory) ) .build()
Java
// Given a CronetEngine and Executor, build a CronetDataSource.Factory. CronetDataSource.Factory cronetDataSourceFactory = new CronetDataSource.Factory(cronetEngine, executor); // Wrap the CronetDataSource.Factory in a DefaultDataSource.Factory, which adds // in support for requesting data from other sources (such as files, resources, // etc). DefaultDataSource.Factory dataSourceFactory = new DefaultDataSource.Factory( context, /* baseDataSourceFactory= */ cronetDataSourceFactory); // Inject the DefaultDataSource.Factory when creating the player. ExoPlayer player = new ExoPlayer.Builder(context) .setMediaSourceFactory( new DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory)) .build();
Pilhas de rede compatíveis
O ExoPlayer oferece suporte direto para HttpEngine, Cronet, OkHttp e a pilha de rede padrão integrada. O ExoPlayer também pode ser estendido para oferecer suporte a pilha de rede que funciona no Android.
Mecanismo HTTP
HttpEngine (em inglês) é a pilha de rede padrão recomendada no Android da API 34 (ou S extensões 7). Na maioria dos casos, ela usa a pilha de rede da Cronet internamente, suporte a HTTP, HTTP/2 e HTTP/3 por protocolos QUIC.
O ExoPlayer oferece suporte ao HttpEngine com a HttpEngineDataSource.Factory
dele. Você pode
injetar essa fábrica de fonte de dados, conforme descrito em Como configurar o ExoPlayer para usar um
pilha de rede específica.
Cronet
Cronet é a A pilha de rede do Chromium foi disponibilizada para os apps Android como uma biblioteca. Tomadas da Cronet vantagem das várias tecnologias que reduzem a latência e aumentam a da capacidade de processamento das solicitações de rede necessárias para o funcionamento do app, incluindo criada pelo ExoPlayer. Ele oferece suporte nativo a HTTP, HTTP/2 e HTTP/3 por QUIC protocolos. A Cronet é usada por alguns dos maiores apps de streaming do mundo, incluindo o YouTube.
O ExoPlayer oferece suporte à Cronet pela
Biblioteca Cronet.
Consulte a README.md
da biblioteca para instruções detalhadas sobre como usar
reimplantá-lo. A biblioteca da Cronet pode usar três elementos
implementações:
- Google Play Services: recomendamos usar essa implementação na maioria dos casos
e usar a pilha de rede integrada do Android
(
DefaultHttpDataSource
) se o Google Play Services não estiver disponível. - Cronet incorporada:pode ser uma boa opção se uma grande porcentagem dos seus usuários estão em mercados onde o Google Play Services não está amplamente disponível ou se você querem controlar a versão exata da implementação da Cronet que está sendo usada. A A principal desvantagem do Cronet Embedded é que ele adiciona aproximadamente 8 MB seu app.
- Substituto da Cronet:a implementação substituta da Cronet implementa
A API da Cronet como um wrapper na pilha de rede integrada do Android. Ele deveria
não pode ser usada com o ExoPlayer, já que usar a pilha de rede integrada do Android
diretamente (usando
DefaultHttpDataSource
) é mais eficiente.
OkHttp
A OkHttp é outra pilha de rede moderna que é amplamente usado por muitos apps Android conhecidos. Ele dá suporte a HTTP e HTTP/2, mas ainda não oferece suporte a HTTP/3 sobre QUIC.
O ExoPlayer oferece suporte ao OkHttp pela
biblioteca OkHttp.
Consulte a README.md
da biblioteca para instruções detalhadas sobre como usar
reimplantá-lo. Ao usar a biblioteca OkHttp, a pilha de rede é incorporada ao
app. É semelhante à Cronet Embedded, mas o OkHttp é significativamente
menor, adicionando menos de 1 MB ao seu aplicativo.
Pilha de rede integrada do Android
O ExoPlayer oferece suporte à pilha de rede integrada do Android com
DefaultHttpDataSource
e DefaultHttpDataSource.Factory
, que fazem parte
biblioteca principal do ExoPlayer.
A implementação exata da pilha de rede depende do software em execução no do dispositivo. Na maioria dos dispositivos, só há suporte para HTTP (ou seja, HTTP/2 e HTTP/3 sobre QUIC não são aceitos).
Outras pilhas de rede
Os apps também podem integrar outras pilhas de rede com o ExoPlayer.
Para fazer isso, implemente um HttpDataSource
que envolva a pilha de rede.
com um HttpDataSource.Factory
correspondente. a Cronet do ExoPlayer e
As bibliotecas OkHttp são bons exemplos de como fazer isso.
Ao fazer a integração com uma pilha de rede Java pura, é uma boa ideia implementar uma
DataSourceContractTest
para verificar se a implementação de HttpDataSource
se comporta corretamente. Na biblioteca OkHttp, o OkHttpDataSourceContractTest
é uma
um bom exemplo de como fazer isso.
Como escolher uma pilha de rede
A tabela a seguir descreve os prós e contras das pilhas de rede com suporte o ExoPlayer.
Pilha de rede | Protocolos | Impacto no tamanho do APK | Observações |
---|---|---|---|
Mecanismo HTTP | HTTP HTTP/2 HTTP/3 por QUIC |
Nenhum | Disponível apenas na API 34 ou nas extensões S7 |
Cronet (Google Play Services) | HTTP HTTP/2 HTTP/3 por QUIC |
Pequeno (<100KB) |
É necessário ter o Google Play Services. Versão da Cronet atualizada automaticamente |
Cronet (incorporada) | HTTP HTTP/2 HTTP/3 por QUIC |
Grande (aproximadamente 8 MB) |
Versão da Cronet controlada pelo desenvolvedor de apps |
Cronet (substituta) | HTTP (varia de acordo com o dispositivo) |
Pequeno (<100KB) |
Não recomendado para o ExoPlayer |
OkHttp | HTTP HTTP/2 |
Pequeno (<1 MB) |
|
Pilha de rede integrada | HTTP (varia de acordo com o dispositivo) |
Nenhum | A implementação varia de acordo com o dispositivo |
Os protocolos HTTP/2 e HTTP/3 via QUIC podem melhorar significativamente as mídias o desempenho do streaming. Em particular, ao transmitir mídia adaptável que é distribuídos por uma rede de distribuição de conteúdo (CDN), existem casos para qual uso desses protocolos pode permitir que as CDNs operem de maneira muito mais eficiente. Por esse motivo, o suporte do HttpEngine e da Cronet a HTTP/2 e HTTP/3 com o QUIC (e o suporte do OkHttp para HTTP/2) é um grande benefício em comparação com usando a pilha de rede integrada do Android, desde que os servidores também são compatíveis com esses protocolos.
Ao considerar o streaming de mídia de forma isolada, recomendamos o uso do HttpEngine ou
A Cronet fornecida pelo Google Play Services com origem em DefaultHttpDataSource
se o Google Play Services estiver indisponível. Essa recomendação é uma boa
equilibrar a ativação do uso de HTTP/2 e HTTP/3 com o QUIC na maioria dos dispositivos
evitando um aumento significativo no tamanho do APK. Há exceções
recomendação. Nos casos em que o Google Play Services pode estar indisponível
em uma parcela significativa de dispositivos que vão executar seu app,
usar a Cronet Embedded ou o OkHttp pode ser mais apropriado. Uso do gerenciador integrado
a pilha de rede pode ser aceitável se o tamanho do APK for uma preocupação crítica ou se a mídia
o streaming é apenas uma pequena parte da funcionalidade do seu app.
Além da mídia, costuma ser uma boa ideia escolher uma pilha de rede para toda a rede realizada pelo seu app. Isso permite que os recursos (como soquetes) para agrupar e compartilhar com eficiência entre o ExoPlayer e outros componentes do app.
Porque seu app provavelmente precisará realizar redes não relacionadas até a reprodução de mídia, sua escolha da pilha de rede deve, em última análise, considerar nossa as recomendações acima para streaming de mídia isoladamente, os requisitos de qualquer outros componentes que realizam redes e sua importância relativa para o seu app.
Armazenamento de mídia em cache
O ExoPlayer oferece suporte ao armazenamento em cache dos bytes carregados no disco para evitar o carregamento repetido os mesmos bytes da rede. Isso é útil ao buscar novamente no estado mídia ou repetir o mesmo item.
O armazenamento em cache requer uma instância SimpleCache
que aponte para um cache dedicado
e um CacheDataSource.Factory
:
Kotlin
// Note: This should be a singleton in your app. val databaseProvider = StandaloneDatabaseProvider(context) // An on-the-fly cache should evict media when reaching a maximum disk space limit. val cache = SimpleCache( downloadDirectory, LeastRecentlyUsedCacheEvictor(maxBytes), databaseProvider) // Configure the DataSource.Factory with the cache and factory for the desired HTTP stack. val cacheDataSourceFactory = CacheDataSource.Factory() .setCache(cache) .setUpstreamDataSourceFactory(httpDataSourceFactory) // Inject the DefaultDataSource.Factory when creating the player. val player = ExoPlayer.Builder(context) .setMediaSourceFactory( DefaultMediaSourceFactory(context).setDataSourceFactory(cacheDataSourceFactory)) .build()
Java
// Note: This should be a singleton in your app. DatabaseProvider databaseProvider = new StandaloneDatabaseProvider(context); // An on-the-fly cache should evict media when reaching a maximum disk space limit. Cache cache = new SimpleCache( downloadDirectory, new LeastRecentlyUsedCacheEvictor(maxBytes), databaseProvider); // Configure the DataSource.Factory with the cache and factory for the desired HTTP stack. DataSource.Factory cacheDataSourceFactory = new CacheDataSource.Factory() .setCache(cache) .setUpstreamDataSourceFactory(httpDataSourceFactory); // Inject the DefaultDataSource.Factory when creating the player. ExoPlayer player = new ExoPlayer.Builder(context) .setMediaSourceFactory( new DefaultMediaSourceFactory(context).setDataSourceFactory(cacheDataSourceFactory)) .build();