لیست های پخش

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 برای ساده‌سازی پیمایش در لیست پخش وجود دارد.

حالت‌های تکرار شونده

این پخش‌کننده از ۳ حالت تکرار پشتیبانی می‌کند که می‌توان آن‌ها را در هر زمانی با 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 از قابلیت shuffling پشتیبانی می‌کند. این قابلیت را می‌توان با ارائه یک پیاده‌سازی سفارشی از ترتیب shuffle یا با تنظیم یک ترتیب سفارشی در سازنده 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 فراخوانی می‌شود. دلایل دیگری که می‌توانند باعث به‌روزرسانی timeline شوند عبارتند از:

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