Redução do APK

Minimizar o tamanho do APK é um aspecto importante do desenvolvimento de um bom app Android. Isso é particularmente verdadeiro ao segmentar mercados em desenvolvimento e também ao desenvolver um Instant App Android. Para esses casos, pode ser desejável minimizar o tamanho da biblioteca do ExoPlayer incluída no APK. Esta página descreve algumas etapas simples que podem ajudar a fazer isso.

Usar apenas as dependências necessárias

depender apenas dos módulos de biblioteca de que você realmente precisa. Por exemplo, o seguinte vai adicionar dependências nos módulos ExoPlayer, DASH e biblioteca de interface, que pode ser necessário para um app que reproduz somente conteúdo DASH:

Kotlin

implementation("androidx.media3:media3-exoplayer:1.3.1")
implementation("androidx.media3:media3-exoplayer-dash:1.3.1")
implementation("androidx.media3:media3-ui:1.3.1")

Groovy

implementation "androidx.media3:media3-exoplayer:1.3.1"
implementation "androidx.media3:media3-exoplayer-dash:1.3.1"
implementation "androidx.media3:media3-ui:1.3.1"

Ativar a redução de código e recursos

Ative a redução de código e recursos nos builds de lançamento do app. O ExoPlayer é estruturado de maneira que permite a redução de código para remover efetivamente as funcionalidades não usadas. Por exemplo, para um app que executa conteúdo DASH, a contribuição do ExoPlayer para o tamanho do APK pode ser reduzida em aproximadamente 40% ativando a redução de código.

Leia Reduzir, ofuscar e otimizar o app para saber como ativar a redução de código e recursos.

Especificar de quais renderizadores seu aplicativo precisa

Por padrão, os renderizadores do player serão criados usando DefaultRenderersFactory. O DefaultRenderersFactory depende de todas as implementações de Renderer fornecidas na biblioteca do ExoPlayer e, como resultado, nenhuma delas será removida pela redução de código. Se você sabe que seu app precisa apenas de um subconjunto de renderizadores, pode especificar seu próprio RenderersFactory. Por exemplo, um app que só toca áudio pode definir uma fábrica como esta ao instanciar instâncias ExoPlayer:

Kotlin

val audioOnlyRenderersFactory =
  RenderersFactory {
    handler: Handler,
    videoListener: VideoRendererEventListener,
    audioListener: AudioRendererEventListener,
    textOutput: TextOutput,
    metadataOutput: MetadataOutput,
    ->
    arrayOf<Renderer>(
      MediaCodecAudioRenderer(context, MediaCodecSelector.DEFAULT, handler, audioListener)
    )
}
val player = ExoPlayer.Builder(context, audioOnlyRenderersFactory).build()

Java

RenderersFactory audioOnlyRenderersFactory =
    (handler, videoListener, audioListener, textOutput, metadataOutput) ->
        new Renderer[] {
            new MediaCodecAudioRenderer(
                context, MediaCodecSelector.DEFAULT, handler, audioListener)
        };
ExoPlayer player = new ExoPlayer.Builder(context, audioOnlyRenderersFactory).build();

Isso permite que outras implementações de Renderer sejam removidas pela redução de código. Neste vídeo de exemplo específico, os renderizadores de texto e metadados são removidos, o que significa que legendas ou metadados in-stream (por exemplo, ICY) não serão processados nem emitidos pelo jogador.

Especificar de quais extratores seu app precisa

Por padrão, o player cria instâncias de Extractor para reproduzir mídia progressiva usando DefaultExtractorsFactory. O DefaultExtractorsFactory depende de todas as implementações de Extractor fornecidas na biblioteca do ExoPlayer e, como resultado, nenhuma delas será removida pela redução de código. Se você sabe que seu app só precisa reproduzir um pequeno número de formatos de contêiner ou não reproduz mídia progressiva, especifique seu próprio ExtractorsFactory. Por exemplo, um app que só precisa reproduzir arquivos mp4 pode oferecer uma fábrica como:

Kotlin

val mp4ExtractorFactory = ExtractorsFactory {
  arrayOf<Extractor>(Mp4Extractor(DefaultSubtitleParserFactory()))
}
val player =
  ExoPlayer.Builder(context, DefaultMediaSourceFactory(context, mp4ExtractorFactory)).build()

Java

ExtractorsFactory mp4ExtractorFactory =
    () -> new Extractor[] {new Mp4Extractor(new DefaultSubtitleParserFactory())};
ExoPlayer player =
    new ExoPlayer.Builder(context, new DefaultMediaSourceFactory(context, mp4ExtractorFactory))
        .build();

Isso permite que outras implementações de Extractor sejam removidas pela redução de código, o que pode resultar em uma redução significativa de tamanho.

Se o app não estiver reproduzindo conteúdo progressivo, transmita ExtractorsFactory.EMPTY para o construtor DefaultMediaSourceFactory e, em seguida, transmita esse mediaSourceFactory para o construtor ExoPlayer.Builder.

Kotlin

val player =
  ExoPlayer.Builder(context, DefaultMediaSourceFactory(context, ExtractorsFactory.EMPTY)).build()

Java

ExoPlayer player =
    new ExoPlayer.Builder(
            context, new DefaultMediaSourceFactory(context, ExtractorsFactory.EMPTY))
        .build();

Instanciação de MediaSource personalizada

Se o app estiver usando um MediaSource.Factory personalizado e você quiser que DefaultMediaSourceFactory seja removido pela remoção de código, transmita o MediaSource.Factory diretamente para o construtor ExoPlayer.Builder.

Kotlin

val player = ExoPlayer.Builder(context, customMediaSourceFactory).build()

Java

ExoPlayer player = new ExoPlayer.Builder(context, mediaSourceFactory).build();

Caso seu app esteja usando MediaSource diretamente em vez de MediaItem, transmita MediaSource.Factory.UNSUPPORTED ao construtor ExoPlayer.Builder para garantir que DefaultMediaSourceFactory e DefaultExtractorsFactory possam ser retirados pela redução de código.

Kotlin

val player = ExoPlayer.Builder(context, MediaSource.Factory.UNSUPPORTED).build()
val mediaSource =
  ProgressiveMediaSource.Factory(dataSourceFactory, customExtractorsFactory)
    .createMediaSource(MediaItem.fromUri(uri))

Java

ExoPlayer player = new ExoPlayer.Builder(context, MediaSource.Factory.UNSUPPORTED).build();
ProgressiveMediaSource mediaSource =
    new ProgressiveMediaSource.Factory(dataSourceFactory, customExtractorsFactory)
        .createMediaSource(MediaItem.fromUri(uri));