יש שתי דרכים להתחבר לאפליקציית מדיה:
MediaControllerMediaBrowser
MediaController
ממשק השליטה במדיה מקיים אינטראקציה עם סשן מדיה כדי לשלוח שאילתות ולשלוט בהפעלה של אפליקציית מדיה. ב-Media3, ממשק ה-API MediaController מטמיע את הממשק Player. דוגמאות לאפליקציות לקוח שמשתמשות בבקר מדיה:
- ממשק השליטה במדיה של מערכת Android
- אפליקציה נלווית ל-Android Wear OS
- Android Auto ו-Automotive OS
- עוזרים קוליים, כמו Google Assistant
- אפליקציית הבדיקה של אמצעי הבקרה של המדיה
בנוסף, ממשק השליטה במדיה יכול להיות שימושי באפליקציית מדיה, למשל אם נגן ומדיה פעילים ב-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());
הצגת רכיבי ה-UI להפעלה של אפליקציית מדיה אחרת
כשמציגים אמצעי בקרה בממשק המשתמש עם לחצנים לאפליקציית מדיה אחרת, חשוב לפעול בהתאם להעדפות לחצני המדיה שהוגדרו באפליקציה הזו.
כדי לפתור את הבעיות בהעדפות של האפליקציה בהתאם למגבלות ולדרישות של ממשק המשתמש, צריך להשתמש ב-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)); }