Redução do APK

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

Usar apenas dependências obrigatórias

Depender apenas dos módulos de biblioteca de que você realmente precisa. Por exemplo, o código abaixo vai adicionar dependências aos módulos da biblioteca ExoPlayer, DASH e UI, como pode ser necessário para um app que só reproduz conteúdo DASH:

Kotlin

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

Groovy

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

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

Ative a redução de código e recursos para os builds de lançamento do app. O ExoPlayer é estruturado de uma maneira que permite que a redução de código remova eficácia a funcionalidade não utilizada. Por exemplo, em um app que reproduz conteúdo DASH, a contribuição do ExoPlayer para o tamanho do APK pode ser reduzida em aproximadamente 40% ao ativar a redução de código.

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

Especificar quais renderizadores o app precisa

Por padrão, os renderizadores do player são criados usando DefaultRenderersFactory. O DefaultRenderersFactory depende de todas as implementações de Renderer fornecidas na biblioteca ExoPlayer. Como resultado, nenhuma delas será removida pelo encurtamento de código. Se você souber que o app só precisa de um subconjunto de renderizadores, especifique o próprio RenderersFactory em vez disso. Por exemplo, um app que só reproduz áudio pode definir uma fábrica como esta ao instanciar instâncias de 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 permitirá que outras implementações de Renderer sejam removidas pelo encolhimento do código. Nesse exemplo de vídeo, os renderizadores de texto e metadados são removidos, o que significa que as legendas ou metadados no stream (por exemplo, ICY) não serão processados nem emitidos pelo reprodutor.

Especificar quais extratores o 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 ExoPlayer. Como resultado, nenhuma delas será removida pelo encurtamento de código. Se você souber que o app precisa reproduzir apenas um pequeno número de formatos de contêiner ou não reproduzir mídia progressiva, especifique o ExtractorsFactory. Por exemplo, um app que só precisa reproduzir arquivos mp4 pode fornecer uma fábrica como esta:

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 pelo encolhimento do código, o que pode resultar em uma redução significativa do tamanho.

Se o app não estiver reproduzindo conteúdo progressivo, transmita ExtractorsFactory.EMPTY para o construtor DefaultMediaSourceFactory e, em seguida, transmita 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 personalizada do MediaSource

Se o app estiver usando um MediaSource.Factory personalizado e você quiser que o DefaultMediaSourceFactory seja removido pelo stripping 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();

Se o app estiver usando MediaSource diretamente em vez de MediaItem, transmita MediaSource.Factory.UNSUPPORTED ao construtor ExoPlayer.Builder para garantir que DefaultMediaSourceFactory e DefaultExtractorsFactory possam ser removidos pelo encurtamento 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));