Zmniejszanie pliku APK

Minimalizowanie rozmiaru pliku APK to ważny aspekt tworzenia dobrej aplikacji na Androida. Przydaje się to szczególnie na rynkach rozwijających się, a także na etapie tworzenia aplikacji błyskawicznej na Androida. W takich przypadkach zalecane może być zminimalizowanie rozmiaru biblioteki ExoPlayer zawartej w pakiecie APK. Na tej stronie opisujemy kilka prostych czynności, które mogą pomóc w osiągnięciu tego celu.

Używaj tylko wymaganych zależności

Korzystaj tylko z modułów bibliotecznych, których potrzebujesz. Na przykład ten tag dodaje zależności od modułów ExoPlayer, DASH i biblioteki UI, co może być wymagane w przypadku aplikacji, która odtwarza tylko treści 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")

Odlotowe

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"

Włącz zmniejszanie kodu i zasobów

Włącz zmniejszanie kodu i zasobów w kompilacjach wersji aplikacji. Struktura ExoPlayer pozwala na zmniejszanie kodu, co pozwala skutecznie usuwać nieużywane funkcje. Na przykład w przypadku aplikacji, która odtwarza treści DASH, udział ExoPlayer w rozmiarze pliku APK można zmniejszyć o około 40% przez włączenie zmniejszenia kodu.

Przeczytaj artykuł Zmniejszanie, zaciemnianie i optymalizowanie aplikacji, aby dowiedzieć się, jak włączyć zmniejszanie kodu i zasobów.

Określ mechanizmy renderowania, których potrzebuje Twoja aplikacja

Domyślnie mechanizmy renderowania odtwarzacza są tworzone za pomocą DefaultRenderersFactory. DefaultRenderersFactory zależy od wszystkich implementacji Renderer dostępnych w bibliotece ExoPlayer, w związku z czym żadna z nich nie zostanie usunięta po zmniejszeniu kodu. Jeśli wiesz, że Twoja aplikacja wymaga tylko podzbioru mechanizmów renderowania, 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 przy tworzeniu 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();

Zmniejszenie kodu pozwoli usunąć inne implementacje Renderer. W tym przykładzie film, tekst i mechanizmy renderowania metadanych są usuwane (co oznacza, że napisy i metadane In-Stream (np. ICY) nie będą przetwarzane ani emitowane przez odtwarzacz).

Określ moduły wyodrębniania potrzebne aplikacji

Domyślnie odtwarzacz tworzy instancje Extractor do odtwarzania multimediów progresywnych za pomocą DefaultExtractorsFactory. DefaultExtractorsFactory zależy od wszystkich implementacji Extractor dostępnych w bibliotece ExoPlayer, w związku z czym żadna z nich nie zostanie usunięta po zmniejszeniu kodu. Jeśli wiesz, że Twoja aplikacja musi odtwarzać tylko niewielką liczbę formatów kontenera lub w ogóle nie odtwarza multimediów progresywnych, możesz określić własny ExtractorsFactory. Na przykład w aplikacji, która wymaga jedynie odtwarzania plików MP4, można utworzyć fabrykę taką jak:

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 kompresowanie kodu spowoduje usunięcie innych implementacji Extractor, co może spowodować znaczne zmniejszenie rozmiaru.

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

Niestandardowa instancja MediaSource

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

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, by mieć pewność, że DefaultMediaSourceFactory i DefaultExtractorsFactory można zmniejszyć przez zmniejszenie 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));