Minimizar el tamaño del APK es un aspecto importante para desarrollar una buena app para Android. Esto es así especialmente cuando se orienta a mercados en desarrollo y también cuando se desarrolla una app instantánea Android. En estos 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 simples 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 biblioteca de ExoPlayer, DASH y de IU, como podría ser necesario para una app que solo reproduce contenido 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"
Habilitar 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 una manera que permite la reducción de código para quitar de manera eficaz la funcionalidad que no se usa. Por ejemplo, en el caso de una app que reproduce contenido DASH, la contribución de ExoPlayer al tamaño del APK se puede reducir aproximadamente un 40% si se habilita la reducción de código.
Consulta el artículo Cómo reducir, ofuscar y optimizar tu app para obtener información sobre cómo habilitar la reducción de código y recursos.
Cómo especificar los procesadores que necesita tu app
De forma predeterminada, los procesadores del reproductor se crearán con DefaultRenderersFactory
. DefaultRenderersFactory
depende de todas las implementaciones de Renderer
proporcionadas en la biblioteca de ExoPlayer y, como resultado, no se quitará ninguna de ellas mediante la reducción de código. Si sabes que tu app solo necesita un subconjunto de procesadores, puedes especificar tu propio RenderersFactory
en su lugar. Por ejemplo, una app que solo reproduce audio puede definir una fábrica como esta cuando se crean 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 se quiten otras implementaciones de Renderer
mediante la reducción de código. En este ejemplo específico de video, se quitan los procesadores de texto y metadatos (lo que significa que el reproductor no procesará ni emitirá los subtítulos ni los metadatos in-stream, como 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
proporcionadas en la biblioteca de ExoPlayer y, como resultado, no se quitará ninguna de ellas mediante la reducción de código. 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 configuración de 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 se quiten otras implementaciones de Extractor
mediante la reducción de código, lo que puede reducir significativamente el tamaño.
Si tu app no reproduce contenido progresivo en absoluto, debes pasar ExtractorsFactory.EMPTY
al constructor DefaultMediaSourceFactory
y, luego, 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 instancias de MediaSource personalizada
Si tu app usa un MediaSource.Factory
personalizado y quieres que se quite DefaultMediaSourceFactory
mediante la eliminación de código, debes pasar el 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 se puedan quitar DefaultMediaSourceFactory
y DefaultExtractorsFactory
mediante la reducción 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));