APK wird kleiner

Die APK-Größe zu minimieren ist ein wichtiger Aspekt bei der Entwicklung einer guten Android-App. Das gilt insbesondere für die Entwicklung von Android Instant Apps und für die Entwicklung für Schwellenländer. In solchen Fällen kann es wünschenswert sein, die Größe der im APK enthaltenen ExoPlayer-Bibliothek zu minimieren. Auf dieser Seite werden einige einfache Schritte beschrieben, die Ihnen dabei helfen können.

Nur erforderliche Abhängigkeiten verwenden

Verwenden Sie nur die Bibliotheksmodule, die Sie tatsächlich benötigen. Im folgenden Beispiel werden Abhängigkeiten von den ExoPlayer-, DASH- und UI-Bibliotheksmodulen hinzugefügt, wie sie möglicherweise für eine App erforderlich sind, die nur DASH-Inhalte wiedergibt:

Kotlin

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

Groovy

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

Verkürzung von Code und Ressourcen aktivieren

Sie sollten die Code- und Ressourcenreduzierung für die Release-Builds Ihrer App aktivieren. ExoPlayer ist so strukturiert, dass durch Code-Shrinking nicht verwendete Funktionen effektiv entfernt werden können. Bei einer App, die DASH-Inhalte wiedergibt, kann der Beitrag von ExoPlayer zur APK-Größe durch Aktivieren von Code-Shrinking um etwa 40% reduziert werden.

Weitere Informationen zum Aktivieren der Code- und Ressourcenreduzierung finden Sie unter App reduzieren, verschleiern und optimieren.

Festlegen, welche Renderer Ihre App benötigt

Standardmäßig werden die Renderer des Players mit DefaultRenderersFactory erstellt. DefaultRenderersFactory hängt von allen Renderer-Implementierungen ab, die in der ExoPlayer-Bibliothek enthalten sind. Daher werden keine von ihnen durch Code-Shrinking entfernt. Wenn Sie wissen, dass Ihre App nur eine Teilmenge von Renderern benötigt, können Sie stattdessen einen eigenen RenderersFactory angeben. Eine App, die nur Audio abspielt, kann beispielsweise beim Instanziieren von ExoPlayer-Instanzen eine Factory so definieren:

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

Dadurch können andere Renderer-Implementierungen durch Code-Shrinking entfernt werden. In diesem Beispielvideo werden Text- und Metadaten-Renderer entfernt. Das bedeutet, dass Untertitel oder In-Stream-Metadaten (z. B. ICY) vom Player nicht verarbeitet oder ausgegeben werden.

Festlegen, welche Extraktoren Ihre App benötigt

Standardmäßig erstellt der Player Extractor-Instanzen, um progressive Medien mit DefaultExtractorsFactory wiederzugeben. DefaultExtractorsFactory hängt von allen Extractor-Implementierungen ab, die in der ExoPlayer-Bibliothek enthalten sind. Daher werden keine von ihnen durch Code-Shrinking entfernt. Wenn Sie wissen, dass Ihre App nur eine kleine Anzahl von Containerformaten abspielen muss oder überhaupt keine progressiven Media abspielt, können Sie stattdessen einen eigenen ExtractorsFactory angeben. Eine App, die beispielsweise nur MP4-Dateien abspielen muss, kann eine Factory wie die folgende bereitstellen:

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

Dadurch können andere Extractor-Implementierungen durch Code-Shrinking entfernt werden, was zu einer erheblichen Größenreduzierung führen kann.

Wenn Ihre App überhaupt keine progressiven Inhalte wiedergibt, sollten Sie ExtractorsFactory.EMPTY an den DefaultMediaSourceFactory-Konstruktor und dann mediaSourceFactory an den ExoPlayer.Builder-Konstruktor übergeben.

Kotlin

val player =
  ExoPlayer.Builder(context, DefaultMediaSourceFactory(context, ExtractorsFactory.EMPTY)).build()

Java

ExoPlayer player =
    new ExoPlayer.Builder(
            context, new DefaultMediaSourceFactory(context, ExtractorsFactory.EMPTY))
        .build();

Benutzerdefinierte MediaSource-Instanziierung

Wenn Ihre App einen benutzerdefinierten MediaSource.Factory verwendet und Sie möchten, dass DefaultMediaSourceFactory durch Code-Stripping entfernt wird, sollten Sie Ihren MediaSource.Factory direkt an den ExoPlayer.Builder-Konstruktor übergeben.

Kotlin

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

Java

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

Wenn Ihre App MediaSource direkt anstelle von MediaItem verwendet, sollten Sie MediaSource.Factory.UNSUPPORTED an den ExoPlayer.Builder-Konstruktor übergeben, damit DefaultMediaSourceFactory und DefaultExtractorsFactory durch Code-Shrinking entfernt werden können.

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