قوائم التشغيل

يتم تحديد واجهة برمجة تطبيقات قائمة التشغيل من خلال واجهة Player التي يتم تنفيذها من خلال جميع عمليات تنفيذ ExoPlayer. تتيح قوائم التشغيل التشغيل التسلسلي لعدة مقاطع ملفات الوسائط. يوضّح المثال التالي كيفية بدء تشغيل قائمة تشغيل. يتضمن مقطعي فيديو:

Kotlin

// Build the media items.
val firstItem = MediaItem.fromUri(firstVideoUri)
val secondItem = MediaItem.fromUri(secondVideoUri)
// Add the media items to be played.
player.addMediaItem(firstItem)
player.addMediaItem(secondItem)
// Prepare the player.
player.prepare()
// Start the playback.
player.play()

Java

// Build the media items.
MediaItem firstItem = MediaItem.fromUri(firstVideoUri);
MediaItem secondItem = MediaItem.fromUri(secondVideoUri);
// Add the media items to be played.
player.addMediaItem(firstItem);
player.addMediaItem(secondItem);
// Prepare the player.
player.prepare();
// Start the playback.
player.play();

تكون الانتقالات بين العناصر في قائمة التشغيل سلسة. ليس هناك أي متطلبات من أنهما بتنسيق واحد (على سبيل المثال، لا مانع من أن تتضمن قائمة التشغيل كلاً من فيديوهات H264 وVP9). حتى أنها قد تكون من أنواع مختلفة (أي أنه لا بأس قائمة التشغيل تحتوي على مقاطع فيديو وصور ومقاطع صوتية فقط). يمكنك استخدام صفحة MediaItem نفسها عدة مرات ضمن قائمة تشغيل.

تعديل قائمة التشغيل

يمكنك تعديل قائمة تشغيل بشكل ديناميكي من خلال إضافة أو نقل أو إزالة أو استبدال ملفات الوسائط. ويمكن إجراء ذلك قبل التشغيل وأثناءه من خلال طلب الطرق المقابلة لواجهة برمجة تطبيقات قوائم التشغيل:

Kotlin

// Adds a media item at position 1 in the playlist.
player.addMediaItem(/* index= */ 1, MediaItem.fromUri(thirdUri))
// Moves the third media item from position 2 to the start of the playlist.
player.moveMediaItem(/* currentIndex= */ 2, /* newIndex= */ 0)
// Removes the first item from the playlist.
player.removeMediaItem(/* index= */ 0)
// Replace the second item in the playlist.
player.replaceMediaItem(/* index= */ 1, MediaItem.fromUri(newUri))

Java

// Adds a media item at position 1 in the playlist.
player.addMediaItem(/* index= */ 1, MediaItem.fromUri(thirdUri));
// Moves the third media item from position 2 to the start of the playlist.
player.moveMediaItem(/* currentIndex= */ 2, /* newIndex= */ 0);
// Removes the first item from the playlist.
player.removeMediaItem(/* index= */ 0);
// Replace the second item in the playlist.
player.replaceMediaItem(/* index= */ 1, MediaItem.fromUri(newUri));

ويمكن أيضًا استبدال قائمة التشغيل ومحوها بالكامل:

Kotlin

// Replaces the playlist with a new one.
val newItems: List<MediaItem> = listOf(MediaItem.fromUri(fourthUri), MediaItem.fromUri(fifthUri))
player.setMediaItems(newItems, /* resetPosition= */ true)
// Clears the playlist. If prepared, the player transitions to the ended state.
player.clearMediaItems()

Java

// Replaces the playlist with a new one.
ImmutableList<MediaItem> newItems =
    ImmutableList.of(MediaItem.fromUri(fourthUri), MediaItem.fromUri(fifthUri));
player.setMediaItems(newItems, /* resetPosition= */ true);
// Clears the playlist. If prepared, the player transitions to the ended state.
player.clearMediaItems();

يعالج المشغّل تلقائيًا التعديلات أثناء التشغيل باللغة الصحيحة الطريقة:

  • في حال تحريك جهاز MediaItem قيد التشغيل حاليًا، لن تتم مقاطعة التشغيل سيتم تشغيل الإصدار الجديد منه عند الانتهاء.
  • في حال إزالة لعبة "MediaItem" التي يتم تشغيلها حاليًا، سيتم تشغيل المشغّل تلقائيًا. تشغيل الوريث الأول المتبقي، أو الانتقال إلى الحالة المنتهية إذا لم وجود مثل هذا الوريث.
  • في حال استبدال جهاز "MediaItem" الذي يتم تشغيله حاليًا، لن تتم مقاطعة التشغيل. إذا لم يكن هناك أي من السمات في MediaItem ذات صلة للتشغيل بتغييره. على سبيل المثال، من الممكن تحديث MediaItem.MediaMetadata. الحقول في معظم الحالات بدون التأثير في التشغيل.

الاستعلام عن قائمة التشغيل

يمكن البحث عن قائمة التشغيل باستخدام Player.getMediaItemCount و Player.getMediaItemAt يمكن الاستعلام عن عنصر الوسائط قيد التشغيل حاليًا عبر الاتصال بالرقم Player.getCurrentMediaItem. هناك أيضًا وسائل راحة أخرى طرق مثل Player.hasNextMediaItem أو Player.getNextMediaItemIndex وتبسيط التنقل في قائمة التشغيل.

أوضاع التكرار

يتيح المشغّل 3 أوضاع تكرار يمكن ضبطها في أي وقت باستخدام Player.setRepeatMode:

  • Player.REPEAT_MODE_OFF: لم يتم تكرار قائمة التشغيل وسينفّذ المشغّلها الانتقال إلى Player.STATE_ENDED بعد انتهاء العنصر الأخير في قائمة التشغيل التي تم لعبها.
  • Player.REPEAT_MODE_ONE: العنصر الحالي يتكرر في تكرار لا نهائي وستتجاهل طرق مثل Player.seekToNextMediaItem هذا الأمر وتسعى إلى العنصر التالي في القائمة، والذي سيتم تكراره بعد ذلك في تكرار لا نهائي.
  • Player.REPEAT_MODE_ALL: يتم تكرار قائمة التشغيل بأكملها بشكل متكرّر.

وضع الترتيب العشوائي

يمكنك تفعيل وضع الترتيب العشوائي أو إيقافه في أي وقت باستخدام Player.setShuffleModeEnabled عندما يكون في وضع الترتيب العشوائي، سيشغل اللاعب قائمة تشغيل بترتيب عشوائي محسوب مسبقًا. سيتم تشغيل جميع العناصر مرة واحدة يمكن أيضًا دمج وضع الترتيب العشوائي مع Player.REPEAT_MODE_ALL لتكرار المهام. بنفس الترتيب العشوائي في تكرار لا نهائي. عند إيقاف وضع الترتيب العشوائي، تشغيل من العنصر الحالي في موضعه الأصلي في قائمة التشغيل.

لاحظ أن الفهارس التي يتم إرجاعها بطرق مثل تشير ميزة Player.getCurrentMediaItemIndex دائمًا إلى المحتوى الأصلي، بدون ترتيب عشوائي. طلبك. وبالمثل، لن يُشغِّل Player.seekToNextMediaItem العنصر في player.getCurrentMediaItemIndex() + 1، ولكن العنصر التالي وفقًا الترتيب العشوائي. سيؤدي إدراج عناصر جديدة في قائمة التشغيل أو إزالة العناصر إلى الإبقاء على الترتيب العشوائي الحالي دون تغيير قدر الإمكان.

ضبط ترتيب عشوائي مخصّص

بشكل تلقائي، يتيح المشغّل الترتيب العشوائي باستخدام DefaultShuffleOrder. يمكن تخصيص هذا من خلال توفير تنفيذ ترتيب عشوائي مخصص، أو من خلال ضبط ترتيب مخصص في الدالة الإنشائية DefaultShuffleOrder:

Kotlin

// Set a custom shuffle order for the 5 items currently in the playlist:
exoPlayer.setShuffleOrder(DefaultShuffleOrder(intArrayOf(3, 1, 0, 4, 2), randomSeed))
// Enable shuffle mode.
exoPlayer.shuffleModeEnabled = true

Java

// Set a custom shuffle order for the 5 items currently in the playlist:
exoPlayer.setShuffleOrder(new DefaultShuffleOrder(new int[] {3, 1, 0, 4, 2}, randomSeed));
// Enable shuffle mode.
exoPlayer.setShuffleModeEnabled(/* shuffleModeEnabled= */ true);

تحديد عناصر قائمة التشغيل

لتحديد عناصر قائمة التشغيل، يمكن ضبط MediaItem.mediaId أثناء إنشاء item:

Kotlin

// Build a media item with a media ID.
val mediaItem = MediaItem.Builder().setUri(uri).setMediaId(mediaId).build()

Java

// Build a media item with a media ID.
MediaItem mediaItem = new MediaItem.Builder().setUri(uri).setMediaId(mediaId).build();

إذا لم يحدّد التطبيق رقم تعريف وسائط لعنصر وسائط بشكل صريح، سيتم استخدام السلسلة يتم استخدام تمثيل عنوان URI.

ربط بيانات التطبيق بعناصر قائمة التشغيل

بالإضافة إلى المعرّف، يمكن أيضًا ضبط كل عنصر من عناصر الوسائط باستخدام علامة مخصّصة والذي يمكن أن يكون أي كائن يوفره التطبيق. ويتمثل أحد استخدامات العلامات المخصصة في إرفاق البيانات الوصفية لكل ملف وسائط:

Kotlin

// Build a media item with a custom tag.
val mediaItem = MediaItem.Builder().setUri(uri).setTag(metadata).build()

Java

// Build a media item with a custom tag.
MediaItem mediaItem = new MediaItem.Builder().setUri(uri).setTag(metadata).build();

رصد انتقال التشغيل إلى عنصر وسائط آخر

عندما ينتقل التشغيل إلى عنصر وسائط آخر أو يبدأ في التكرار ملف الوسائط، يُسمى Listener.onMediaItemTransition(MediaItem, @MediaItemTransitionReason). يتلقّى معاودة الاتصال هذه الوسائط الجديدة بالإضافة إلى @MediaItemTransitionReason الذي يشير إلى سبب انتقال حدث. وتتمثل حالة الاستخدام الشائعة لـ onMediaItemTransition في تعديل واجهة مستخدم التطبيق لعنصر الوسائط الجديد:

Kotlin

override fun onMediaItemTransition(
  mediaItem: MediaItem?,
  @MediaItemTransitionReason reason: Int,
) {
  updateUiForPlayingMediaItem(mediaItem)
}

Java

@Override
public void onMediaItemTransition(
    @Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) {
  updateUiForPlayingMediaItem(mediaItem);
}

إذا تم إرفاق البيانات الوصفية المطلوبة لتحديث واجهة المستخدم بكل عنصر وسائط باستخدام العلامات المخصصة، فقد تظهر عملية التنفيذ على النحو التالي:

Kotlin

override fun onMediaItemTransition(
  mediaItem: MediaItem?,
  @MediaItemTransitionReason reason: Int,
) {
  var metadata: CustomMetadata? = null
  mediaItem?.localConfiguration?.let { localConfiguration ->
    metadata = localConfiguration.tag as? CustomMetadata
  }
  updateUiForPlayingMediaItem(metadata)
}

Java

@Override
public void onMediaItemTransition(
    @Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) {
  @Nullable CustomMetadata metadata = null;
  if (mediaItem != null && mediaItem.localConfiguration != null) {
    metadata = (CustomMetadata) mediaItem.localConfiguration.tag;
  }
  updateUiForPlayingMediaItem(metadata);
}

اكتشاف تغيُّر قائمة التشغيل

عند إضافة ملف وسائط أو إزالته أو نقله اسم "Listener.onTimelineChanged(Timeline, @TimelineChangeReason)" فورًا باستخدام TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED. معاودة الاتصال هذه يتم استدعاؤها حتى عندما لا يكون اللاعب مستعدًا بعد.

Kotlin

override fun onTimelineChanged(timeline: Timeline, @TimelineChangeReason reason: Int) {
  if (reason == Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED) {
    // Update the UI according to the modified playlist (add, move or remove).
    updateUiForPlaylist(timeline)
  }
}

Java

@Override
public void onTimelineChanged(Timeline timeline, @TimelineChangeReason int reason) {
  if (reason == TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED) {
    // Update the UI according to the modified playlist (add, move or remove).
    updateUiForPlaylist(timeline);
  }
}

عندما تصبح معلومات مثل مدة محتوى الوسائط في قائمة التشغيل متاح، سيتم تحديث Timeline وسيتم الاتصال بـ onTimelineChanged. مع TIMELINE_CHANGE_REASON_SOURCE_UPDATE. الأسباب الأخرى التي قد تتسبب في تحديث الجدول الزمني ما يلي:

  • بيان يصبح متاحًا بعد إعداد عنصر وسائط تكيُّفي.
  • بيان يتم تعديله بشكل دوري أثناء تشغيل بث مباشر.