هناك طريقتان للربط بتطبيق وسائط:
MediaControllerMediaBrowser
MediaController
تتفاعل وحدة التحكّم في الوسائط مع جلسة وسائط للاستعلام عن تشغيل تطبيق وسائط والتحكّم فيه. في Media3، تنفّذ واجهة برمجة التطبيقات MediaController واجهة Player. تشمل أمثلة تطبيقات العميل التي تستخدم وحدة التحكّم في الوسائط ما يلي:
- أدوات التحكّم في الوسائط في نظام Android
- التطبيق المصاحب لنظام التشغيل Android Wear OS
- Android Auto ونظام التشغيل Automotive
- المساعدات الصوتية، مثل مساعد Google
- تطبيق Media Controller Test
يمكن أن تكون وحدة التحكّم في الوسائط مفيدة أيضًا داخل تطبيق موسيقى، على سبيل المثال إذا كانت جلسة المشغّل والوسائط تعمل في Service منفصل عن Activity أو Fragment مع واجهة المستخدم.
إنشاء MediaController
لإنشاء MediaController، ابدأ بإنشاء SessionToken لـ MediaSession المقابل. يمكن أن تكون طريقة onStart() في Activity أو Fragment مكانًا جيدًا لذلك.
Kotlin
val sessionToken = SessionToken(context, ComponentName(context, PlaybackService::class.java))
Java
SessionToken sessionToken = new SessionToken(context, new ComponentName(context, PlaybackService.class));
يؤدي استخدام SessionToken لإنشاء MediaController إلى ربط وحدة التحكّم بالجلسة المحدّدة. يتم ذلك بشكل غير متزامن، لذا عليك
الانتظار حتى تظهر النتيجة واستخدامها عند توفّرها.
Kotlin
val controllerFuture = MediaController.Builder(context, sessionToken).buildAsync() controllerFuture.addListener( { // MediaController is available here with controllerFuture.get() }, MoreExecutors.directExecutor(), )
Java
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() عند قطع اتصال وحدة التحكّم
بالجلسة.
يمكن ضبط MediaController.Listener عند إنشاء وحدة التحكّم باستخدام
Builder:
Kotlin
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()
Java
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.
Kotlin
MediaController.releaseFuture(controllerFuture)
Java
MediaController.releaseFuture(controllerFuture);
سيؤدي تحرير وحدة التحكّم إلى إرسال جميع الأوامر المعلّقة إلى الجلسة وإلغاء الربط بخدمة الجلسة فقط بعد معالجة هذه الأوامر أو بعد انتهاء مهلة، أيهما يحدث أولاً.
MediaBrowser
تعتمد MediaBrowser على الإمكانات التي توفّرها MediaController لإتاحة تصفُّح مكتبة الوسائط التي يوفّرها MediaLibraryService لتطبيق الوسائط.
إنشاء MediaBrowser
Kotlin
val browserFuture = MediaBrowser.Builder(context, sessionToken).buildAsync() browserFuture.addListener( { // MediaBrowser is available here with browserFuture.get() }, MoreExecutors.directExecutor(), )
Java
ListenableFuture<MediaBrowser> browserFuture = new MediaBrowser.Builder(context, sessionToken).buildAsync(); browserFuture.addListener( () -> { // MediaBrowser is available here with browserFuture.get() }, MoreExecutors.directExecutor());
استخدام MediaBrowser
لبدء تصفُّح مكتبة محتوى تطبيق الوسائط، عليك أولاً استرداد العقدة الجذر
باستخدام getLibraryRoot():
Kotlin
// 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(), )
Java
// 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:
Kotlin
// 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(), )
Java
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 لتشغيل الإجراء المرتبط في تطبيق
الوسائط.
Kotlin
// 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) }, ) }
Java
// 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)); }