تقليص حزمة APK

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

استخدام التبعيات المطلوبة فقط

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

أنيق

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"

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

يجب تفعيل ميزة تقليص الرموز والموارد في إصدارات تطبيقك. تم تصميم 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));