رابط پخش کننده

پخش‌کننده (player) بخشی از برنامه شماست که پخش آیتم‌های رسانه‌ای را تسهیل می‌کند. رابط کاربری Media3 Player طرحی کلی برای عملکردهایی که عموماً توسط یک پخش‌کننده انجام می‌شود، تنظیم می‌کند. این شامل موارد زیر است:

  • تأثیرگذاری بر کنترل‌های پخش، مانند پخش، مکث و جستجو
  • پرس‌وجو از ویژگی‌های رسانه در حال پخش، مانند موقعیت پخش
  • مدیریت لیست پخش/صف اقلام رسانه‌ای
  • پیکربندی ویژگی‌های پخش، مانند پخش تصادفی، تکرار، سرعت و میزان صدا
  • رندر کردن ویدیو روی صفحه نمایش

Media3 همچنین پیاده‌سازی از رابط Player را با نام ExoPlayer ارائه می‌دهد.

رابط مشترک بین اجزا

چندین کامپوننت در Media3 رابط پخش‌کننده را پیاده‌سازی می‌کنند، برای مثال:

کامپوننت توضیحات و یادداشت‌های رفتاری
ExoPlayer یک API پخش‌کننده‌ی رسانه، و پیاده‌سازی پیش‌فرض رابط Player .
MediaController برای ارسال دستورات پخش با MediaSession تعامل دارد. اگر Player و MediaSession شما در یک Service جدا از Activity یا Fragment که رابط کاربری Player شما در آن قرار دارد، هستند، می‌توانید MediaController خود را به عنوان پخش‌کننده برای رابط کاربری PlayerView خود اختصاص دهید. فراخوانی‌های متدهای پخش و لیست پخش از طریق MediaSession به Player شما ارسال می‌شوند.
MediaBrowser علاوه بر قابلیت‌های ارائه شده توسط MediaController ، با MediaLibrarySession برای مرور محتوای رسانه‌ای موجود تعامل دارد.
SimpleBasePlayer پیاده‌سازی Player که تعداد متدهای لازم برای پیاده‌سازی را به حداقل می‌رساند. این قابلیت هنگام استفاده از یک پخش‌کننده سفارشی که می‌خواهید به یک MediaSession متصل کنید، مفید است.
ForwardingSimpleBasePlayer یک زیرکلاس SimpleBasePlayer که برای ارسال عملیات پخش به Player دیگر طراحی شده است، در حالی که امکان سفارشی‌سازی‌های رفتاری ثابتی مانند SimpleBasePlayer را فراهم می‌کند. از این کلاس برای سرکوب یا تغییر عملیات پخش خاص استفاده کنید.
CastPlayer یک پیاده‌سازی Player که با یک برنامه گیرنده Cast ارتباط برقرار می‌کند. رفتار آن به جلسه Cast زیربنایی بستگی دارد.

اگرچه یک MediaSession رابط Player را پیاده‌سازی نمی‌کند، اما هنگام ایجاد آن به یک Player نیاز دارد. هدف آن فراهم کردن دسترسی به Player از طریق سایر فرآیندها یا نخ‌ها است.

معماری پخش Media3

اگر به Player دسترسی دارید، باید متدهای آن را مستقیماً برای صدور دستورات پخش فراخوانی کنید. می‌توانید با پیاده‌سازی MediaSession پخش خود را اعلام کنید و به منابع خارجی کنترل پخش را اعطا کنید. این منابع خارجی یک MediaController پیاده‌سازی می‌کنند که اتصال به یک جلسه رسانه و صدور درخواست‌های دستور پخش را تسهیل می‌کند.

هنگام پخش رسانه در پس‌زمینه، باید جلسه رسانه و پخش‌کننده خود را در یک MediaSessionService یا MediaLibraryService که به عنوان یک سرویس پیش‌زمینه اجرا می‌شود، قرار دهید. اگر این کار را انجام دهید، می‌توانید پخش‌کننده خود را از Activity در برنامه خود که شامل رابط کاربری برای کنترل پخش است، جدا کنید. این ممکن است مستلزم استفاده از یک کنترل‌کننده رسانه باشد.

نموداری که نشان می‌دهد چگونه اجزای پخش Media3 در معماری یک برنامه رسانه‌ای جای می‌گیرند.
شکل ۱ : رابط کاربری Player نقش کلیدی در معماری Media3 ایفا می‌کند.

وضعیت بازیکن

وضعیت یک پخش‌کننده رسانه که رابط Player را پیاده‌سازی می‌کند، عمدتاً از 4 دسته اطلاعات تشکیل شده است:

  1. وضعیت پخش
  2. لیست پخش موارد رسانه‌ای
  3. ویژگی‌های پخش/مکث، مانند:
    • playWhenReady : نشانه‌ای از اینکه آیا کاربر می‌خواهد رسانه در صورت امکان پخش شود یا در حالت مکث باقی بماند
    • دلیل توقف پخش : نشانه‌ای از اینکه چرا پخش متوقف می‌شود، در صورت وجود، حتی اگر playWhenReady true داشته باشد
    • isPlaying : نشانه‌ای از اینکه آیا پخش‌کننده در حال پخش است یا خیر، که تنها در صورتی true خواهد بود که وضعیت پخش STATE_READY باشد، playWhenReady true باشد و پخش متوقف نشده باشد.
  4. موقعیت پخش، شامل:

علاوه بر این، رابط کاربری Player امکان دسترسی به آهنگ‌های موجود ، ابرداده‌های رسانه‌ای ، سرعت پخش ، میزان صدا و سایر ویژگی‌های کمکی پخش را فراهم می‌کند.

به تغییرات گوش دهید

از یک Player.Listener برای گوش دادن به تغییرات در یک Player استفاده کنید. برای جزئیات بیشتر در مورد نحوه ایجاد و استفاده از یک listener، به مستندات ExoPlayer در مورد رویدادهای Player مراجعه کنید.

توجه داشته باشید که رابط شنونده هیچ فراخوانی برای ردیابی پیشرفت پخش عادی ندارد. برای نظارت مداوم بر پیشرفت پخش، مانند تنظیم رابط کاربری نوار پیشرفت، باید موقعیت فعلی را در فواصل مناسب پرس و جو کنید.

کاتلین

val handler = Handler(Looper.getMainLooper())
fun checkPlaybackPosition(delayMs: Long): Boolean =
  handler.postDelayed(
    {
      val currentPosition = player.currentPosition
      // Update UI based on currentPosition
      checkPlaybackPosition(delayMs)
    },
    delayMs)

جاوا

Handler handler = new Handler(Looper.getMainLooper());
boolean checkPlaybackPosition(long delayMs) {
    return handler.postDelayed(() -> {
        long currentPosition = player.getCurrentPosition();
        // Update UI based on currentPosition
        checkPlaybackPosition(delayMs);
    }, delayMs);
}

کنترل پخش

رابط کاربری Player روش‌های زیادی برای دستکاری وضعیت و کنترل پخش ارائه می‌دهد:

پیاده‌سازی‌های Player سفارشی

برای ایجاد یک پخش‌کننده‌ی سفارشی، می‌توانید SimpleBasePlayer موجود در Media3 را گسترش دهید. این کلاس یک پیاده‌سازی پایه از رابط Player ارائه می‌دهد تا تعداد متدهایی که باید پیاده‌سازی کنید را به حداقل برساند.

با بازنویسی متد getState() شروع کنید. این متد باید هنگام فراخوانی، وضعیت فعلی بازیکن را شامل موارد زیر، در خود جای دهد:

  • مجموعه دستورات موجود
  • ویژگی‌های پخش، مانند اینکه آیا پخش‌کننده باید وقتی وضعیت پخش STATE_READY است، پخش را شروع کند یا خیر، اندیس آیتم رسانه‌ای در حال پخش و موقعیت پخش در آیتم فعلی

کاتلین

class CustomPlayer : SimpleBasePlayer(looper) {
  override fun getState(): State {
    return State.Builder()
      .setAvailableCommands(...) // Set which playback commands the player can handle
      // Configure additional playback properties
      .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST)
      .setCurrentMediaItemIndex(0)
      .setContentPositionMs(0)
      .build()
  }
}

جاوا

public class CustomPlayer extends SimpleBasePlayer {
  public CustomPlayer(Looper looper) {
    super(looper);
  }

  @Override
  protected State getState() {
    return new State.Builder()
      .setAvailableCommands(...) // Set which playback commands the player can handle
      // Configure additional playback properties
      .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST)
      .setCurrentMediaItemIndex(0)
      .setContentPositionMs(0)
      .build();
  }
}

SimpleBasePlayer تضمین می‌کند که State با ترکیبی معتبر از مقادیر state ایجاد شده باشد. همچنین listenerها را مدیریت کرده و listenerها را از تغییرات state مطلع می‌کند. اگر نیاز دارید که به‌روزرسانی state را به صورت دستی فعال کنید، invalidateState() را فراخوانی کنید.

فراتر از متد getState() ، شما فقط باید متدهایی را پیاده‌سازی کنید که برای دستوراتی که پخش‌کننده شما اعلام می‌کند در دسترس هستند، استفاده می‌شوند. متد کنترل‌کننده‌ی قابل لغوی را که مربوط به عملکردی است که می‌خواهید پیاده‌سازی کنید، پیدا کنید. برای مثال، متد handleSeek() را برای پشتیبانی از عملیاتی مانند COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM و COMMAND_SEEK_TO_NEXT_MEDIA_ITEM لغو کنید.

اصلاح پیاده‌سازی‌های Player

به جای ایجاد یک Player کاملاً سفارشی، می‌توانید از ForwardingSimpleBasePlayer برای تغییر وضعیت و رفتار یک Player موجود استفاده کنید. برای جزئیات بیشتر به راهنمای صفحه Customization مراجعه کنید.