Pilhas de rede

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:

  1. 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.
  2. 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. O A principal desvantagem do Cronet Embedded é que ele adiciona aproximadamente 8 MB seu app.
  3. 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. Para 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 a importância relativa deles 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 repetindo 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();