Zmniejszanie pliku APK

Minimalizowanie rozmiaru pliku APK jest ważnym aspektem tworzenia dobrej aplikacji na Androida. Jest to szczególnie istotne w przypadku rynków rozwijających się, a także podczas tworzenia aplikacji błyskawicznej na Androida. W takich przypadkach warto zminimalizować rozmiar biblioteki ExoPlayer, która jest dołączona do pliku APK. Na tej stronie znajdziesz kilka prostych czynności, które pomogą Ci to osiągnąć.

Używaj tylko wymaganych zależności

Korzystaj tylko z modułów biblioteki, których rzeczywiście potrzebujesz. Na przykład poniższy kod doda zależności od modułów biblioteki ExoPlayer, DASH i UI, co może być wymagane w przypadku aplikacji, która odtwarza tylko treści DASH:

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"

Włącz kompresowanie kodu i zasobów

W przypadku kompilacji aplikacji do publikacji należy włączyć zmniejszanie kodu i zasobów. ExoPlayer jest skonstruowany w taki sposób, aby zmniejszanie kodu skutecznie usuwało nieużywane funkcje. Na przykład w przypadku aplikacji, która odtwarza treści DASH, udział ExoPlayera w rozmiarze pliku APK można zmniejszyć o około 40% przez włączenie zmniejszania kodu.

Więcej informacji o włączaniu zmniejszania kodu i zasobów znajdziesz w artykule Zmniejszanie, zaciemnianie i optymalizowanie aplikacji.

Określ, których modułów renderujących potrzebuje Twoja aplikacja

Domyślnie renderery odtwarzacza będą tworzone za pomocą funkcji DefaultRenderersFactory. DefaultRenderersFactory zależy od wszystkich implementacji Renderer udostępnionych w bibliotece ExoPlayer, dlatego żadna z nich nie zostanie usunięta przez zmniejszanie kodu. Jeśli wiesz, że Twoja aplikacja potrzebuje tylko podzbioru rendererów, możesz zamiast tego określić własny RenderersFactory. Na przykład aplikacja, która odtwarza tylko dźwięk, może zdefiniować fabrykę w ten sposób podczas tworzenia instancji 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();

Umożliwi to usunięcie innych implementacji Renderer przez zmniejszenie kodu. W tym konkretnym przykładzie wideo usuwane są renderery tekstu i metadanych (co oznacza, że żadne napisy ani metadane w strumieniu (np. ICY) nie będą przetwarzane ani emitowane przez odtwarzacz).

Określ, których ekstraktorów potrzebuje Twoja aplikacja

Domyślnie odtwarzacz tworzy instancje Extractor do odtwarzania progresywnych multimediów za pomocą DefaultExtractorsFactory. DefaultExtractorsFactory zależy od wszystkich implementacji Extractor udostępnionych w bibliotece ExoPlayer, dlatego żadna z nich nie zostanie usunięta przez zmniejszanie kodu. Jeśli wiesz, że Twoja aplikacja obsługuje tylko niewielką liczbę formatów kontenerów lub w ogóle nie odtwarza mediów progresywnych, możesz zamiast tego określić własną wartość ExtractorsFactory. Na przykład aplikacja, która musi tylko odtwarzać pliki MP4, może udostępniać fabrykę w ten sposób:

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

Dzięki temu inne implementacje Extractor można usunąć za pomocą zmniejszania kodu, co może znacznie zmniejszyć rozmiar aplikacji.

Jeśli Twoja aplikacja w ogóle nie odtwarza treści progresywnych, przekaż wartość ExtractorsFactory.EMPTY do konstruktora DefaultMediaSourceFactory, a następnie przekaż ten obiekt mediaSourceFactory do konstruktora 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();

Niestandardowe tworzenie instancji MediaSource

Jeśli Twoja aplikacja używa niestandardowego MediaSource.Factory i chcesz, aby został on usunięty przez wycinanie kodu, przekaż MediaSource.Factory bezpośrednio do konstruktora ExoPlayer.Builder.DefaultMediaSourceFactory

Kotlin

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

Java

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

Jeśli Twoja aplikacja używa bezpośrednio MediaSource zamiast MediaItem, przekaż MediaSource.Factory.UNSUPPORTED do konstruktora ExoPlayer.Builder, aby mieć pewność, że DefaultMediaSourceFactoryDefaultExtractorsFactory można usunąć za pomocą zmniejszania kodu.

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