Reducción de APK

Minimizar el tamaño del APK es un aspecto importante para desarrollar una buena app para Android, en especial cuando se orienta a mercados en desarrollo y cuando se desarrolla una app instantánea Android. En esos casos, puede ser conveniente minimizar el tamaño de la biblioteca de ExoPlayer que se incluye en el APK. En esta página, se describen algunos pasos sencillos que pueden ayudarte a lograrlo.

Usa solo las dependencias necesarias

Depende solo de los módulos de biblioteca que realmente necesites. Por ejemplo, lo siguiente agregará dependencias en los módulos de la biblioteca de ExoPlayer, DASH y la IU, como podría ser necesario para una app que solo reproduce contenido de DASH:

Kotlin

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

Groovy

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

Habilita la reducción de código y recursos

Debes habilitar la reducción de código y recursos para las compilaciones de lanzamiento de tu app. ExoPlayer está estructurado de manera que permite que la reducción de código quite de forma eficaz las funciones que no se usan. Por ejemplo, en el caso de una app que reproduce contenido de DASH, la contribución de ExoPlayer al tamaño del APK se puede reducir en aproximadamente un 40% si se habilita la reducción de código.

Lee Cómo reducir, ofuscar y optimizar tu app para aprender a habilitar la reducción de código y recursos.

Especifica qué renderizadores necesita tu app

De forma predeterminada, los renderizadores del reproductor se crearán con DefaultRenderersFactory. DefaultRenderersFactory depende de todas las implementaciones de Renderer que se proporcionan en la biblioteca de ExoPlayer y, como resultado, la reducción de código no quitará ninguna de ellas. Si sabes que tu app solo necesita un subconjunto de renderizadores, puedes especificar tu propio RenderersFactory. Por ejemplo, una app que solo reproduce audio puede definir una fábrica como esta cuando crea instancias 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();

Esto permitirá que la reducción de código quite otras implementaciones de Renderer. En este ejemplo de video en particular, se quitan los renderizadores de texto y metadatos (lo que significa que el reproductor no procesará ni emitirá subtítulos ni metadatos en la transmisión, p.ej., ICY).

Especifica qué extractores necesita tu app

De forma predeterminada, el reproductor crea instancias de Extractor para reproducir contenido multimedia progresivo con DefaultExtractorsFactory. DefaultExtractorsFactory depende de todas las implementaciones de Extractor que se proporcionan en la biblioteca de ExoPlayer y, como resultado, la reducción de código no quitará ninguna de ellas. Si sabes que tu app solo necesita reproducir una pequeña cantidad de formatos de contenedor o no reproduce contenido multimedia progresivo, puedes especificar tu propio ExtractorsFactory. Por ejemplo, una app que solo necesita reproducir archivos MP4 puede proporcionar una fábrica como la siguiente:

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

Esto permitirá que la reducción de código quite otras implementaciones de Extractor, lo que puede generar una disminución significativa del tamaño.

Si tu app no reproduce contenido progresivo, debes pasar ExtractorsFactory.EMPTY al constructor DefaultMediaSourceFactory y, luego, pasar ese mediaSourceFactory al constructor 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();

Creación de una instancia de MediaSource personalizada

Si tu app usa un MediaSource.Factory personalizado y quieres que se quite DefaultMediaSourceFactory con la eliminación de código, debes pasar tu MediaSource.Factory directamente al constructor ExoPlayer.Builder.

Kotlin

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

Java

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

Si tu app usa MediaSource directamente en lugar de MediaItem, debes pasar MediaSource.Factory.UNSUPPORTED al constructor ExoPlayer.Builder para asegurarte de que la reducción de código pueda quitar DefaultMediaSourceFactory y DefaultExtractorsFactory.

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