Zmniejszanie pliku APK

Zminimalizowanie rozmiaru pliku APK jest ważnym aspektem tworzenia dobrej aplikacji na Androida. Dotyczy to zwłaszcza rynków rozwijających się, a także tworzenia aplikacji błyskawicznej na Androida. W takich przypadkach warto zminimalizować rozmiar biblioteki ExoPlayer dołączonej do pliku APK. Na tej stronie znajdziesz kilka prostych kroków, które pomogą Ci to osiągnąć.

Używaj tylko wymaganych zależności

Zależ od modułów biblioteki, których faktycznie potrzebujesz. Na przykład poniższy kod doda zależności od modułów biblioteki ExoPlayer, DASH i UI, które mogą być wymagane w przypadku aplikacji odtwarzającej tylko treści DASH:

Kotlin

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

Dynamiczny

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

Włączanie zmniejszania kodu i zasobów

W kompilacjach do publikacji aplikacji należy włączyć zmniejszanie kodu i zasobów. ExoPlayer ma strukturę, która umożliwia zmniejszanie kodu w celu skutecznego usuwania nieużywanych funkcji. Na przykład w przypadku aplikacji, która odtwarza treści DASH, włączenie zmniejszania kodu może zmniejszyć wpływ ExoPlayera na rozmiar pliku APK o około 40%.

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

Określanie, których mechanizmów renderowania potrzebuje aplikacja

Domyślnie renderery odtwarzacza będą tworzone za pomocą DefaultRenderersFactory. DefaultRenderersFactory zależy od wszystkich implementacji Renderer dostępnych w bibliotece ExoPlayer, dlatego żadna z nich nie zostanie usunięta podczas zmniejszania kodu. Jeśli wiesz, że Twoja aplikacja potrzebuje tylko podzbioru modułów renderujących, możesz określić własny element 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();

Dzięki temu inne implementacje Renderer będzie można usunąć przez zmniejszanie kodu. W tym konkretnym przykładowym filmie renderery tekstu i metadanych są usuwane (co oznacza, że napisy lub metadane w strumieniu, np. ICY, nie będą przetwarzane ani emitowane przez odtwarzacz).

Określanie ekstraktorów, których potrzebuje aplikacja

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, dlatego żadna z nich nie zostanie usunięta podczas zmniejszania kodu. Jeśli wiesz, że aplikacja musi odtwarzać tylko niewielką liczbę formatów kontenerów lub w ogóle nie odtwarza multimediów progresywnych, możesz zamiast tego określić własny obiekt ExtractorsFactory. Na przykład aplikacja, która musi odtwarzać tylko 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ąć przez zmniejszenie kodu, co może znacznie zmniejszyć rozmiar.

Jeśli aplikacja w ogóle nie odtwarza treści progresywnych, przekaż ExtractorsFactory.EMPTY do konstruktora DefaultMediaSourceFactory, a następnie przekaż 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 obiektu MediaSource.Factory i chcesz, aby obiekt DefaultMediaSourceFactory został usunięty przez usuwanie kodu, przekaż obiekt 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, musisz przekazać MediaSource.Factory.UNSUPPORTED do konstruktora ExoPlayer.Builder, aby mieć pewność, że DefaultMediaSourceFactory i DefaultExtractorsFactory mogą zostać usunięte przez zmniejszanie 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));