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 a seguir 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.4.1")
implementation("androidx.media3:media3-exoplayer-dash:1.4.1")
implementation("androidx.media3:media3-ui:1.4.1")

Groovy

implementation "androidx.media3:media3-exoplayer:1.4.1"
implementation "androidx.media3:media3-exoplayer-dash:1.4.1"
implementation "androidx.media3:media3-ui:1.4.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 seu próprio RenderersFactory. 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 permite 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 ou emitidos pelo player.

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 encolhimento 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));