Zmniejszanie pliku APK

Minimalizowanie rozmiaru pliku APK jest ważnym aspektem tworzenia dobrej aplikacji na Androida. Jest to szczególnie ważne w przypadku kierowania na rynki rozwijające się, a także podczas tworzenia aplikacji błyskawicznej na Androida. W takich przypadkach warto zminimalizować rozmiar biblioteki ExoPlayer zawartej w pliku APK. Na tej stronie znajdziesz kilka prostych instrukcji, które pomogą Ci to osiągnąć.

Używaj tylko wymaganych zależności.

Używaj tylko tych modułów biblioteki, których rzeczywiście potrzebujesz. Na przykład poniższy kod spowoduje dodanie zależności od modułów bibliotek 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.4.1")
implementation("androidx.media3:media3-exoplayer-dash:1.4.1")
implementation("androidx.media3:media3-ui:1.4.1")

Groovy

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

Włączanie kompresji kodu i zasobów

W przypadku kompilacji do publikacji aplikacji należy włączyć kompresowanie kodu i zasobów. ExoPlayer jest skonstruowany w sposób, który umożliwia zmniejszanie kodu w celu skutecznego usuwania nieużywanych funkcji. Na przykład w przypadku aplikacji odtwarzającej treści DASH rozmiar pliku APK może zostać zmniejszony o około 40% dzięki włączeniu kompresji kodu.

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

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

Domyślnie moduły renderujące odtwarzacza są 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 kompresję kodu. Jeśli wiesz, że Twoja aplikacja potrzebuje tylko podzbioru rendererów, możesz zamiast tego podać własne 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();

Pozwoli to na usunięcie innych implementacji Renderer przez kompresję kodu. W tym przykładowym filmie usunięto elementy renderujące tekst i metadane (co oznacza, że żadne napisy ani metadane w filmie (np. ICY) nie będą przetwarzane ani emitowane przez odtwarzacz).

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

Domyślnie odtwarzacz tworzy instancje Extractor, aby odtwarzać media progresywne za pomocą DefaultExtractorsFactory. DefaultExtractorsFactory zależy od wszystkich implementacji Extractor udostępnionych w bibliotece ExoPlayer, dlatego żadna z nich nie zostanie usunięta przez kompresję kodu. Jeśli wiesz, że Twoja aplikacja musi odtwarzać tylko niewielką liczbę formatów kontenerów lub wcale nie odtwarza progresywnych multimediów, możesz zamiast tego podać własne ExtractorsFactory. Na przykład aplikacja, która musi tylko odtwarzać pliki mp4, może mieć fabrykę:

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 zostaną usunięte przez kompresję kodu, co może spowodować znaczne zmniejszenie rozmiaru.

Jeśli aplikacja w ogóle nie odtwarza treści progresywnych, prześlij ExtractorsFactory.EMPTY do konstruktora DefaultMediaSourceFactory, a potem prześlij 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();

Tworzenie instancji niestandardowego obiektu MediaSource

Jeśli Twoja aplikacja używa niestandardowej wartości MediaSource.Factory i chcesz, aby została ona usunięta przez usuwanie kodu, przekaż wartość 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, konstruktorowi ExoPlayer.Builder należy przekazać wartość MediaSource.Factory.UNSUPPORTED, aby można było usunąć elementy DefaultMediaSourceFactoryDefaultExtractorsFactory podczas kompresji 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));