Riduzione APK

La minimizzazione delle dimensioni dell'APK è un aspetto importante dello sviluppo di una buona app Android. Ciò è particolarmente vero quando si prendono di mira i mercati in via di sviluppo e anche quando si sviluppa un'app istantanea Android. In questi casi, potrebbe essere preferibile ridurre al minimo le dimensioni della libreria ExoPlayer inclusa nell'APK. Questa pagina descrive alcuni semplici passaggi che possono aiutarti a raggiungere questo obiettivo.

Utilizzare solo le dipendenze richieste

Dipendi solo dai moduli della libreria di cui hai effettivamente bisogno. Ad esempio, quanto segue aggiungerà le dipendenze dai moduli della libreria ExoPlayer, DASH e UI, come potrebbe essere richiesto per un'app che riproduce solo contenuti DASH:

Kotlin

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

Alla moda

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

Attivare la riduzione del codice e delle risorse

Devi attivare la riduzione del codice e delle risorse per le build di release della tua app. ExoPlayer è strutturato in modo da consentire alla riduzione del codice di rimuovere efficacemente le funzionalità inutilizzate. Ad esempio, per un'app che riproduce contenuti DASH, il contributo di ExoPlayer alle dimensioni dell'APK può essere ridotto di circa il 40% attivando la riduzione del codice.

Leggi Ridurre, offuscare e ottimizzare l'app per scoprire come attivare la riduzione del codice e delle risorse.

Specificare i renderer di cui ha bisogno l'app

Per impostazione predefinita, i renderer del player vengono creati utilizzando DefaultRenderersFactory. DefaultRenderersFactory dipende da tutte le implementazioni di Renderer fornite nella libreria ExoPlayer e, di conseguenza, nessuna di queste verrà rimossa dalla riduzione del codice. Se sai che la tua app ha bisogno solo di un sottoinsieme di renderer, puoi specificare il tuo RenderersFactory. Ad esempio, un'app che riproduce solo audio può definire una factory come questa quando crea un'istanza di 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();

In questo modo, le altre implementazioni di Renderer possono essere rimosse dalla riduzione del codice. In questo video di esempio, i renderer di testo e metadati vengono rimossi (il che significa che i sottotitoli o i metadati in streaming (ad es. ICY) non verranno elaborati o emessi dal player).

Specificare gli estrattori di cui ha bisogno l'app

Per impostazione predefinita, il player crea Extractor istanze per riprodurre contenuti multimediali progressivi utilizzando DefaultExtractorsFactory. DefaultExtractorsFactory dipende da tutte le implementazioni di Extractor fornite nella libreria ExoPlayer e, di conseguenza, nessuna di esse verrà rimossa dalla riduzione del codice. Se sai che la tua app deve riprodurre solo un numero limitato di formati di container o non riproduce affatto contenuti multimediali progressivi, puoi specificare il tuo ExtractorsFactory. Ad esempio, un'app che deve riprodurre solo file MP4 può fornire una factory come:

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

In questo modo, le altre implementazioni di Extractor possono essere rimosse dalla riduzione del codice, il che può comportare una riduzione significativa delle dimensioni.

Se la tua app non riproduce affatto contenuti progressivi, devi passare ExtractorsFactory.EMPTY al costruttore DefaultMediaSourceFactory, quindi passare mediaSourceFactory al costruttore 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();

Creazione di un'istanza di MediaSource personalizzata

Se la tua app utilizza un MediaSource.Factory personalizzato e vuoi che DefaultMediaSourceFactory venga rimosso dalla rimozione del codice, devi passare MediaSource.Factory direttamente al costruttore ExoPlayer.Builder.

Kotlin

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

Java

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

Se la tua app utilizza MediaSource direttamente anziché MediaItem, devi passare MediaSource.Factory.UNSUPPORTED al costruttore ExoPlayer.Builder, per assicurarti che DefaultMediaSourceFactory e DefaultExtractorsFactory possano essere rimossi dalla riduzione del codice.

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