تقليص حزمة APK

يُعدّ تقليل حجم حزمة APK جانبًا مهمًا في تطوير تطبيق Android جيد، وينطبق ذلك بشكل خاص عند استهداف الأسواق النامية، وكذلك عند تطوير تطبيق فوري على Android. وفي مثل هذه الحالات، قد يكون من المستحسن تقليل حجم مكتبة ExoPlayer المضمّنة في حزمة APK. توضّح هذه الصفحة بعض الخطوات البسيطة التي يمكن أن تساعد في تحقيق ذلك.

استخدام العناصر التابعة المطلوبة فقط

استخدِم وحدات المكتبة التي تحتاج إليها فقط. على سبيل المثال، سيؤدي ما يلي إلى إضافة تبعيات على وحدات مكتبة ExoPlayer وDASH وواجهة المستخدم، كما قد يكون مطلوبًا لتطبيق يعرض محتوى 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"

تفعيل تصغير الرموز والموارد

يجب تفعيل تخفيض حجم الرموز والموارد في إصدارات تطبيقك. تم تصميم ExoPlayer بطريقة تتيح تخفيض حجم الرموز البرمجية لإزالة الوظائف غير المستخدَمة بشكل فعّال. على سبيل المثال، بالنسبة إلى تطبيق يشغّل محتوى DASH، يمكن تقليل مساهمة ExoPlayer في حجم حزمة APK بنسبة% 40 تقريبًا من خلال تفعيل تصغير الرمز.

يمكنك الاطّلاع على مقالة تصغير حجم تطبيقك وإخفاء مفاتيح فك التشفير وتحسينه للتعرّف على كيفية تفعيل تصغير حجم الرموز والموارد.

تحديد أدوات العرض التي يحتاجها تطبيقك

سيتم تلقائيًا إنشاء أدوات العرض الخاصة بالمشغّل باستخدام DefaultRenderersFactory. تعتمد DefaultRenderersFactory على جميع عمليات التنفيذ Renderer المتوفّرة في مكتبة ExoPlayer، ونتيجةً لذلك، لن تتم إزالة أيّ منها من خلال تصغير الرمز البرمجي. إذا كنت تعلم أنّ تطبيقك يحتاج فقط إلى مجموعة فرعية من أدوات العرض، يمكنك تحديد RenderersFactory بنفسك بدلاً من ذلك. على سبيل المثال، يمكن لتطبيق يشغّل الصوت فقط تحديد عنصر مثل هذا عند إنشاء مثيلات 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();

سيسمح ذلك بإزالة عمليات تنفيذ Renderer الأخرى من خلال تصغير الرمز البرمجي. في مثال الفيديو هذا، تتم إزالة أدوات عرض النصوص والبيانات الوصفية (ما يعني أنّ أي ترجمة وشرح أو بيانات وصفية مضمّنة في البث (مثل ICY) لن تتم معالجتها أو عرضها من خلال المشغّل).

تحديد أدوات الاستخراج التي يحتاجها تطبيقك

ينشئ المشغّل تلقائيًا مثيلات Extractor لتشغيل الوسائط المتدفقة باستخدام DefaultExtractorsFactory. تعتمد DefaultExtractorsFactory على جميع عمليات التنفيذ Extractor المتوفّرة في مكتبة ExoPlayer، ونتيجةً لذلك، لن تتم إزالة أيّ منها من خلال تصغير الرمز البرمجي. إذا كنت تعلم أنّ تطبيقك يحتاج فقط إلى تشغيل عدد صغير من تنسيقات الحاويات، أو أنّه لا يشغّل الوسائط المتدفقة على الإطلاق، يمكنك تحديد ExtractorsFactory خاص بك بدلاً من ذلك. على سبيل المثال، يمكن لتطبيق يحتاج فقط إلى تشغيل ملفات mp4 توفير عنصر على النحو التالي:

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

سيسمح ذلك بإزالة عمليات تنفيذ Extractor الأخرى من خلال تصغير الرمز البرمجي، ما قد يؤدي إلى تقليل الحجم بشكل كبير.

إذا كان تطبيقك لا يعرض المحتوى بشكل تدريجي على الإطلاق، عليك تمرير ExtractorsFactory.EMPTY إلى الدالة الإنشائية DefaultMediaSourceFactory، ثم تمرير mediaSourceFactory إلى الدالة الإنشائية 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();

إنشاء مثيل مخصّص لفئة MediaSource

إذا كان تطبيقك يستخدم MediaSource.Factory مخصّصًا وأردت إزالة DefaultMediaSourceFactory من خلال عملية إزالة الرموز البرمجية، عليك تمرير MediaSource.Factory مباشرةً إلى أداة إنشاء ExoPlayer.Builder.

Kotlin

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

Java

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

إذا كان تطبيقك يستخدم MediaSource مباشرةً بدلاً من MediaItem، عليك تمرير MediaSource.Factory.UNSUPPORTED إلى الدالة الإنشائية ExoPlayer.Builder، وذلك لضمان إمكانية إزالة DefaultMediaSourceFactory وDefaultExtractorsFactory من خلال تصغير الرمز البرمجي.

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