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.
Przeczytaj artykuł Zmniejszanie, zaciemnianie i optymalizowanie aplikacji, aby dowiedzieć się, jak włączyć zmniejszanie kodu i zasobów.
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. W rezultacie ż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 zostaną przetworzone ani wyemitowane przez odtwarzacz).
Określ moduły wyodrębniania potrzebne aplikacji
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 ma 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 podczas kompresji kodu, co może znacznie zmniejszyć rozmiar.
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 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 metody MediaSource
zamiast MediaItem
, konstruktorowi ExoPlayer.Builder
należy przekazać wartość MediaSource.Factory.UNSUPPORTED
, aby można było usunąć wartości DefaultMediaSourceFactory
i DefaultExtractorsFactory
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));