متصل شدن به برنامه رسانه

دو روش برای اتصال به برنامه رسانه‌ای وجود دارد:

  1. MediaController
  2. MediaBrowser

MediaController

کنترل‌کننده رسانه با جلسه رسانه تعامل می‌کند تا از برنامه رسانه بازپخش را پُرسمان و کنترل کند. در Media3، میانای برنامه‌سازی کاربردی MediaController Player را پیاده‌سازی می‌کند. نمونه‌هایی از برنامه‌های مشتری که از کنترل‌کننده رسانه استفاده می‌کنند عبارت‌اند از:

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

ایجاد MediaController

برای ایجاد MediaController، ابتدا SessionToken را برای MediaSession مربوطه ایجاد کنید. روش onStart() در Activity یا Fragment می‌تواند جای خوبی برای این کار باشد.

کاتلین

val sessionToken = SessionToken(context, ComponentName(context, PlaybackService::class.java))

جاوا

SessionToken sessionToken =
    new SessionToken(context, new ComponentName(context, PlaybackService.class));

استفاده از این SessionToken برای ساختن MediaController، کنترل‌کننده را به جلسه داده‌شده متصل می‌کند. این کار به‌صورت ناهمزمان انجام می‌شود، بنابراین باید منتظر نتیجه بمانید و وقتی دردسترس قرار گرفت از آن استفاده کنید.

کاتلین

val controllerFuture = MediaController.Builder(context, sessionToken).buildAsync()
controllerFuture.addListener(
  {
    // MediaController is available here with controllerFuture.get()
  },
  MoreExecutors.directExecutor(),
)

جاوا

ListenableFuture<MediaController> controllerFuture =
    new MediaController.Builder(context, sessionToken).buildAsync();
controllerFuture.addListener(
    () -> {
      // MediaController is available here with controllerFuture.get()
    },
    MoreExecutors.directExecutor());

استفاده از MediaController

‫MediaController رابط Player را پیاده‌سازی می‌کند، بنابراین می‌توانید از دستورهای تعریف‌شده در رابط برای کنترل بازپخش MediaSession متصل استفاده کنید. یعنی فراخوانی play() در MediaController فرمان را به MediaSession متصل ارسال می‌کند، که سپس فرمان را به Player زیرین خود واگذار می‌کند.

می‌توانید Player.Listener را به کنترل‌کننده اضافه کنید تا تغییرات وضعیت Player را بشنود. برای جزئیات بیشتر درباره استفاده از Player.Listener، به راهنمای رویدادهای پخش‌کننده مراجعه کنید.

میانای MediaController.Listener برگشت‌های تماس اضافی برای رویدادها و فرمان‌های سفارشی از MediaSession متصل را تعریف می‌کند. برای مثال، onCustomCommand() وقتی جلسه فرمان سفارشی ارسال می‌کند، onAvailableSessionCommandsChanged() وقتی جلسه فرمان‌های جلسه دردسترس را تغییر می‌دهد، یا onDisconnected() وقتی کنترل‌کننده از جلسه قطع می‌شود.

هنگام ساختن کنترل‌کننده با Builder، می‌توان MediaController.Listener را تنظیم کرد:

کاتلین

val controllerFuture =
  MediaController.Builder(context, sessionToken)
    .setListener(
      object : MediaController.Listener {
        override fun onCustomCommand(
          controller: MediaController,
          command: SessionCommand,
          args: Bundle,
        ): ListenableFuture<SessionResult> {
          // Handle custom command.
          return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
        }

        override fun onDisconnected(controller: MediaController) {
          // Handle disconnection.
        }
      }
    )
    .buildAsync()

جاوا

ListenableFuture<MediaController> controllerFuture =
    new MediaController.Builder(context, sessionToken)
        .setListener(
            new MediaController.Listener() {
              @Override
              public ListenableFuture<SessionResult> onCustomCommand(
                  MediaController controller, SessionCommand command, Bundle args) {
                // Handle custom command.
                return Futures.immediateFuture(new SessionResult(SessionResult.RESULT_SUCCESS));
              }

              @Override
              public void onDisconnected(MediaController controller) {
                // Handle disconnection.
              }
            })
        .buildAsync();

مانند سایر عناصر، به‌یاد داشته باشید که وقتی دیگر به MediaController نیاز ندارید، آن را آزاد کنید، مثلاً در روش onStop() در Activity یا Fragment.

کاتلین

MediaController.releaseFuture(controllerFuture)

جاوا

MediaController.releaseFuture(controllerFuture);

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

MediaBrowser

MediaBrowser با بهره‌گیری از قابلیت‌های ارائه‌شده توسط MediaController، امکان مرور کتابخانه رسانه‌ای ارائه‌شده توسط MediaLibraryService برنامه رسانه‌ای را نیز فراهم می‌کند.

ایجاد MediaBrowser

کاتلین

val browserFuture = MediaBrowser.Builder(context, sessionToken).buildAsync()
browserFuture.addListener(
  {
    // MediaBrowser is available here with browserFuture.get()
  },
  MoreExecutors.directExecutor(),
)

جاوا

ListenableFuture<MediaBrowser> browserFuture =
    new MediaBrowser.Builder(context, sessionToken).buildAsync();
browserFuture.addListener(
    () -> {
      // MediaBrowser is available here with browserFuture.get()
    },
    MoreExecutors.directExecutor());

استفاده از MediaBrowser

برای شروع مرور کتابخانه محتوای برنامه رسانه، ابتدا گره ریشه را با getLibraryRoot() بازیابی کنید:

کاتلین

// Get the library root to start browsing the library tree.
val rootFuture = mediaBrowser.getLibraryRoot(/* params= */ null)
rootFuture.addListener(
  {
    // Root node MediaItem is available here with rootFuture.get().value
  },
  MoreExecutors.directExecutor(),
)

جاوا

// Get the library root to start browsing the library tree.
ListenableFuture<LibraryResult<MediaItem>> rootFuture =
    mediaBrowser.getLibraryRoot(/* params= */ null);
rootFuture.addListener(
    () -> {
      // Root node MediaItem is available here with rootFuture.get().value
    },
    MoreExecutors.directExecutor());

سپس می‌توانید با بازیابی فرزندان MediaItem در کتابخانه با getChildren()، در کتابخانه رسانه پیمایش کنید. برای مثال، برای بازیابی فرزندان گره ریشه MediaItem:

کاتلین

// Get the library root to start browsing the library tree.
val childrenFuture = mediaBrowser.getChildren(rootMediaItem.mediaId, 0, Int.MAX_VALUE, null)
childrenFuture.addListener(
  {
    // List of children MediaItem nodes is available here with
    // childrenFuture.get().value
  },
  MoreExecutors.directExecutor(),
)

جاوا

ListenableFuture<LibraryResult<ImmutableList<MediaItem>>> childrenFuture =
    mediaBrowser.getChildren(rootMediaItem.mediaId, 0, Integer.MAX_VALUE, null);
childrenFuture.addListener(
    () -> {
      // List of children MediaItem nodes is available here with
      // childrenFuture.get().value
    },
    MoreExecutors.directExecutor());

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

هنگام نمایش کنترل‌های رابط کاربری با دکمه‌های برنامه رسانه‌ای دیگر، مهم است که از اولویت‌های دکمه رسانه اعلام‌شده آن برنامه پیروی کنید.

برای حل کردن اولویت‌های برنامه با محدودیت‌ها و الزامات واسط کاربر، از CommandButton.DisplayConstraints استفاده کنید. می‌توانید محدودیت‌ها و ممنوعیت‌های رابط کاربری‌تان را تعریف کنید، و روش resolve() فهرست مشخصی از دکمه‌ها را برای نمایش با نماد، موقعیت، و کنش موردنظر ارائه می‌دهد. اگر کاربری روی یکی از این دکمه‌ها کلیک کند، می‌توانید از CommandButton.executeAction برای راه‌اندازی کنش مرتبط در برنامه رسانه استفاده کنید.

کاتلین

// Get media button preferences from media app
val mediaButtonPreferences = controller.getMediaButtonPreferences()
// Declare constraints of UI (example: limit overflow button to one)
val displayConstraints =
  DisplayConstraints.Builder().setMaxButtonsForSlot(CommandButton.SLOT_OVERFLOW, 1).build()
// Resolve media app preferences with constraints
val resolvedButtons = displayConstraints.resolve(mediaButtonPreferences, controller)
// Display buttons in UI
for (button in resolvedButtons) {
  generateUiButton(
    uiPosition = button.slots[0],
    icon = getIconRes(button.icon),
    onClick = { button.executeAction(controller) },
  )
}

جاوا

// Get media button preferences from media app
List<CommandButton> mediaButtonPreferences = controller.getMediaButtonPreferences();
// Declare constraints of UI (example: limit overflow button to one)
DisplayConstraints displayConstraints =
    new DisplayConstraints.Builder()
        .setMaxButtonsForSlot(CommandButton.SLOT_OVERFLOW, 1)
        .build();
// Resolve media app preferences with constraints
List<CommandButton> resolvedButtons =
    displayConstraints.resolve(mediaButtonPreferences, controller);
// Display buttons in UI
for (CommandButton button : resolvedButtons) {
  generateUiButton(
      /* uiPosition= */ button.slots.get(0),
      /* icon= */ getIconRes(button.icon),
      /* onClick= */ () -> button.executeAction(controller));
}