لیست های پخش

API لیست پخش توسط رابط Player تعریف می شود که توسط تمام پیاده سازی های ExoPlayer پیاده سازی می شود. لیست های پخش، پخش متوالی آیتم های چند رسانه ای را فعال می کنند. مثال زیر نحوه شروع پخش یک لیست پخش حاوی دو ویدیو را نشان می دهد:

کاتلین

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

جاوا

// 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 چندین بار در یک لیست پخش استفاده کنید.

تغییر لیست پخش

شما می توانید به صورت پویا یک لیست پخش را با افزودن، جابجایی، حذف یا جایگزینی آیتم های رسانه تغییر دهید. این را می توان هم قبل و هم در حین پخش با فراخوانی روش های API لیست پخش مربوطه انجام داد:

کاتلین

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

جاوا

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

جایگزینی و پاک کردن کل لیست پخش نیز پشتیبانی می شود:

کاتلین

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

جاوا

// 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 : کل لیست پخش در یک حلقه بی پایان تکرار می شود.

حالت زدن

حالت Shuffle را می توان در هر زمان با Player.setShuffleModeEnabled فعال یا غیرفعال کرد. هنگامی که در حالت زدن، پخش کننده لیست پخش را به ترتیب تصادفی از پیش محاسبه شده پخش می کند. همه آیتم‌ها یک بار پخش می‌شوند و حالت مخلوط کردن نیز می‌تواند با Player.REPEAT_MODE_ALL ترکیب شود تا همان ترتیب تصادفی‌شده را در یک حلقه بی‌پایان تکرار کند. وقتی حالت shuffle خاموش است، پخش از آیتم فعلی در موقعیت اصلی خود در لیست پخش ادامه می یابد.

توجه داشته باشید که شاخص‌هایی که با روش‌هایی مانند Player.getCurrentMediaItemIndex برگردانده می‌شوند، همیشه به ترتیب اصلی و ترکیب نشده اشاره می‌کنند. به طور مشابه، Player.seekToNextMediaItem آیتم را در player.getCurrentMediaItemIndex() + 1 پخش نمی کند، بلکه آیتم بعدی را طبق ترتیب ترکیبی پخش می کند. درج موارد جدید در لیست پخش یا حذف موارد، ترتیب ترکیبی موجود را تا آنجا که ممکن است بدون تغییر نگه می‌دارد.

تنظیم یک ترتیب ترکیبی سفارشی

به‌طور پیش‌فرض، پخش‌کننده با استفاده از DefaultShuffleOrder از زدن پشتیبانی می‌کند. این را می توان با ارائه یک پیاده سازی سفارشی سفارشی سفارشی یا با تنظیم یک سفارش سفارشی در سازنده DefaultShuffleOrder سفارشی کرد:

کاتلین

// 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

جاوا

// 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 را می توان در هنگام ساختن آیتم تنظیم کرد:

کاتلین

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

جاوا

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

اگر یک برنامه به صراحت یک شناسه رسانه برای یک آیتم رسانه تعریف نکند، از نمایش رشته ای URI استفاده می شود.

مرتبط کردن داده های برنامه با موارد لیست پخش

علاوه بر شناسه، هر آیتم رسانه ای را می توان با یک برچسب سفارشی نیز پیکربندی کرد، که می تواند هر شیء ارائه شده از برنامه باشد. یکی از کاربردهای تگ های سفارشی، پیوست کردن ابرداده به هر آیتم رسانه ای است:

کاتلین

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

جاوا

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

تشخیص زمانی که پخش به یک مورد رسانه دیگر منتقل می شود

هنگامی که پخش به یک آیتم رسانه دیگر منتقل می شود یا شروع به تکرار همان آیتم رسانه ای می کند، Listener.onMediaItemTransition(MediaItem, @MediaItemTransitionReason) فراخوانی می شود. این پاسخ تماس، آیتم رسانه ای جدید را به همراه یک @MediaItemTransitionReason دریافت می کند که نشان می دهد چرا این انتقال رخ داده است. یک مورد رایج برای onMediaItemTransition به روز رسانی رابط کاربری برنامه برای آیتم رسانه جدید است:

کاتلین

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

جاوا

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

اگر ابرداده مورد نیاز برای به‌روزرسانی رابط کاربری با استفاده از برچسب‌های سفارشی به هر یک از آیتم‌های رسانه متصل شود، پیاده‌سازی ممکن است به این صورت باشد:

کاتلین

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

جاوا

@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 فراخوانی می‌شود. این کال بک حتی زمانی که بازیکن هنوز آماده نشده باشد فراخوانی می شود.

کاتلین

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

جاوا

@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 فراخوانی می‌شود. دلایل دیگری که می تواند باعث بروز رسانی جدول زمانی شود عبارتند از:

  • یک مانیفست پس از تهیه یک آیتم رسانه تطبیقی ​​در دسترس قرار می گیرد.
  • مانیفست به‌طور دوره‌ای در حین پخش جریانی زنده به‌روزرسانی می‌شود.