الصور

يتوافق ExoPlayer مع تنسيقات الصور التالية. اطّلِع على مكتبات تحميل الصور للتعرّف على كيفية الدمج مع المكتبات الخارجية التي قد توفّر دعمًا لمجموعة مختلفة من التنسيقات.

تنسيق الصورة معلومات معتمَدة ملاحظات
BMP نعم
ملف GIF لا لا تتوفّر أداة استخراج
JPEG نعم
صورة متحركة بتنسيق JPEG نعم الصور الثابتة والفيديوهات المتوافقة
دقة HDR فائقة بتنسيق JPEG نعم يتم الرجوع إلى SDR قبل Android 14 أو على الشاشات غير المزوّدة بتقنية النطاق العالي الديناميكية
PNG نعم
WebP نعم
HEIF/HEIC نعم
صورة حيّة بتنسيق HEIC جزئيًا تتوفّر الصور الثابتة فقط*
‫AVIF (الأساسي) نعم يتم فك ترميزها على الإصدار 14 من نظام التشغيل Android والإصدارات الأحدث فقط.

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

استخدام MediaItem

لتشغيل صورة كجزء من قائمة تشغيل، أنشئ MediaItem باستخدام عنوان URL للصورة وقدِّمه إلى المشغّل. يجب أن يتضمّن MediaItem imageDurationMs لتحديد مدّة عرض الصورة.

Kotlin

// Create a player instance.
val player = ExoPlayer.Builder(context).build()
// Set the media item to be played with the desired duration.
player.setMediaItem(
    MediaItem.Builder().setUri(imageUri).setImageDurationMs(2000).build())
// Prepare the player.
player.prepare()

Java

// Create a player instance.
ExoPlayer player = new ExoPlayer.Builder(context).build();
// Set the media item to be played with the desired duration.
player.setMediaItem(
    new MediaItem.Builder().setUri(imageUri).setImageDurationMs(2000).build());
// Prepare the player.
player.prepare();

الصور الحيّة

الصور الحيّة هي ملفات تجمع بين صورة ثابتة وفيديو قصير.

  • إذا تم تحديد مدة الصورة باستخدام setImageDuration، يتم عرض الصورة الحيّة كصورة ثابتة خلال المدة المحدّدة.
  • إذا لم يتم تحديد مدة الصورة، يتم تشغيل الصورة الحيّة كفيديو.

استخدام ProgressiveMediaSource

لمزيد من خيارات التخصيص، يمكنك إنشاء ProgressiveMediaSource ونقله مباشرةً إلى المشغّل بدلاً من MediaItem.

Kotlin

// Create a data source factory.
val dataSourceFactory = DefaultHttpDataSource.Factory()
// Create a media item with the image URI and the desired duration.
val mediaItem =
    MediaItem.Builder().setUri(imageUri).setImageDurationMs(2000).build()
// Create a progressive media source for this media item.
val mediaSource =
    ProgressiveMediaSource.Factory(dataSourceFactory)
        .createMediaSource(mediaItem)
// Create a player instance.
val player = ExoPlayer.Builder(context).build()
// Set the media source to be played.
player.setMediaSource(mediaSource)
// Prepare the player.
player.prepare()

Java

// Create a data source factory.
DataSource.Factory dataSourceFactory = new DefaultHttpDataSource.Factory();
// Create a media item with the image URI and the desired duration.
MediaItem mediaItem =
    new MediaItem.Builder().setUri(imageUri).setImageDurationMs(2000).build();
// Create a progressive media source for this media item.
MediaSource mediaSource =
    new ProgressiveMediaSource.Factory(dataSourceFactory)
        .createMediaSource(mediaItem);
// Create a player instance.
ExoPlayer player = new ExoPlayer.Builder(context).build();
// Set the media source to be played.
player.setMediaSource(mediaSource);
// Prepare the player.
player.prepare();

تخصيص عملية التشغيل

يقدّم ExoPlayer طرقًا متعدّدة لتخصيص تجربة التشغيل وفقًا لاحتياجات تطبيقك. اطّلِع على صفحة التخصيص للحصول على أمثلة.

مكتبات تحميل الصور

غالبًا ما تتم إدارة الصور من خلال مكتبات تحميل صور خارجية، مثل Glide أو Coil.

يتطلب دمج هذه المكتبات في مسار التشغيل 3 خطوات:

  1. حدِّد MediaItem بنوع MIME APPLICATION_EXTERNALLY_LOADED_IMAGE.
  2. قدِّم وحدة فك ترميز الصور لاسترداد Bitmap من مكتبة تحميل الصور.
  3. قدِّم أداة تحميل خارجية لبدء ميزة التخزين المؤقت وميزة التحميل المُسبَق.

عنصر MediaItem بنوع MIME لصورة تم تحميلها خارجيًا

يجب أن تحدِّد القيمة MediaItem المُضافة إلى القيمة Player نوع APPLICATION_EXTERNALLY_LOADED_IMAGE MIME بشكل صريح لاستخدام مسارات رمز مكتبة تحميل الصور:

Kotlin

val mediaItem =
  MediaItem.Builder()
    .setUri(imageUri)
    .setMimeType(MimeTypes.APPLICATION_EXTERNALLY_LOADED_IMAGE)
    .build()

Java

MediaItem mediaItem =
    new MediaItem.Builder()
        .setUri(imageUri)
        .setMimeType(MimeTypes.APPLICATION_EXTERNALLY_LOADED_IMAGE)
        .build();

أداة فك ترميز الصور باستخدام مكتبة لتحميل الصور

يحتاج مشغّل العرض إلى ExternallyLoadedImageDecoder لاسترداد Bitmap من Uri. يمكن توفير هذا الترميز من خلال إلغاء DefaultRenderersFactory.getImageDecoderFactory.

يستخدم المثال التالي Glide لتحميل صورة:

Kotlin

val glideImageDecoderFactory: ImageDecoder.Factory =
  ExternallyLoadedImageDecoder.Factory { request: ExternalImageRequest ->
    GlideFutures.submit(Glide.with(context).asBitmap().load(request.uri))
  }
val player: Player =
  ExoPlayer.Builder(context)
    .setRenderersFactory(
      object : DefaultRenderersFactory(context) {
        override fun getImageDecoderFactory(): ImageDecoder.Factory {
          return glideImageDecoderFactory
        }
      }
    )
    .build()

Java

ImageDecoder.Factory glideImageDecoderFactory =
    new ExternallyLoadedImageDecoder.Factory(
        request -> GlideFutures.submit(
            Glide.with(context).asBitmap().load(request.uri)));
Player player =
    new ExoPlayer.Builder(context)
        .setRenderersFactory(
            new DefaultRenderersFactory(context) {
              @Override
              protected ImageDecoder.Factory getImageDecoderFactory() {
                return glideImageDecoderFactory;
              }
            })
        .build();

تحميل الصور مسبقًا باستخدام مكتبة لتحميل الصور

أثناء التشغيل، يطلب المشغّل تحميل الصورة التالية مسبقًا بعد تحميل العنصر السابق في قائمة التشغيل بالكامل. عند استخدام مكتبة loading خارجية لتحميل الصور، يجب تحديد ExternalLoader لبدء عملية التحميل المُسبَق هذه. إذا لم يكن التمهيد المُسبَق ممكنًا أو مطلوبًا، يجب توفير أداة التحميل هذه، ولكن لن تتمكّن من تنفيذ أي إجراء.

يستخدم المثال التالي Glide لضمان تحميل الصورة المطلوبة مسبقًا إلى القرص:

Kotlin

val glidePreloader = ExternalLoader { request: LoadRequest ->
  GlideFutures.submit(
    Glide.with(context)
      .asFile()
      .apply(
        RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.DATA)
          .priority(Priority.HIGH)
          .skipMemoryCache(true)
      )
      .load(request.uri)
  )
}

Java

ExternalLoader glidePreloader =
    request ->
        GlideFutures.submit(
            Glide.with(context)
                .asFile()
                .apply(
                    diskCacheStrategyOf(DiskCacheStrategy.DATA)
                        .priority(Priority.HIGH)
                        .skipMemoryCache(true))
                .load(request.uri));