שליטה במדיה באמצעות MediaSession

1. מבוא

העדכון האחרון: 2020-09-09

מה היתרונות של הוספת MediaSession להפעלת סרטונים?

סשנים של מדיה הם קישור אינטגרלי בין פלטפורמת Android לבין אפליקציות מדיה. הוא לא רק מעדכן את Android שמדיה מופעלת – כדי שמערכת ההפעלה תוכל להעביר פעולות שקשורות למדיה לסשן הנכון – אלא גם מעדכן את הפלטפורמה לגבי מה שמופעל ואיך אפשר לשלוט בהפעלה.

חשיפת MediaSession דרך האפליקציה מספקת יתרונות שונים למשתמשים. הנה כמה דוגמאות מצוינות.

Google Assistant

המשתמשים יכולים ליצור אינטראקציה בקלות עם המדיה באפליקציה באמצעות פקודות קוליות כמו 'השהיה', 'המשך ההפעלה' ו'הבא'. אפשר גם להשתמש במטא-נתונים מהמדיה כדי לקבל תשובות לגבי מה שמופעל כרגע.

Android TV

בממשקים למסך גדול, אפליקציה ל-Android TV יכולה להשתמש בשלטים רגילים עבור משתמשים עם טלוויזיות שתומכות ב-HDMI-CEC. הפקודות שמופעלות באמצעות הלחצנים 'הפעלה/השהיה', 'עצירה', 'הבא' ו'הקודם' מועברות לאפליקציה.

אמצעי בקרה להפעלת מדיה במסך

החל מ-Android 4.0 (רמת API‏ 14), המערכת יכולה לגשת למצב ההפעלה ולמטא-נתונים של סשן מדיה. הפונקציונליות הזו מאפשרת להציג במסך הנעילה את אמצעי הבקרה של המדיה ואת יצירת האומנות. ההתנהגות הזו משתנה בהתאם לגרסת Android.

מדיה ברקע

אפשר לשלוט במדיה בכל אחד מהתרחישים האלה, גם אם האפליקציה שמפעילה את המדיה פועלת ברקע.

מחשוב סביבתי

חשיפת המדיה שלכם עם נתונים על מה שמופעל ואיך אפשר לשלוט בה יכולה לגשר בין מכשירים, כך שהמשתמשים יוכלו ליצור איתה אינטראקציה במגוון דרכים שהם אוהבים.

מה תפַתחו

בשיעור Codelab הזה, נרחיב את הדוגמה הקיימת של Exoplayer כדי להוסיף תמיכה בסשן מדיה. האפליקציה שלכם:

  • לשקף בצורה נכונה את המצב הפעיל של סשן המדיה
  • העברת פקדי מדיה ל-ExoPlayer
  • העברת מטא-נתונים של פריטים בתור להפעלה של המדיה

מה תלמדו

  • למה סשנים של מדיה מציעים למשתמשים חוויה עשירה יותר
  • איך יוצרים סשן מדיה ומנהלים את המצב שלו
  • איך מקשרים סשן מדיה ל-ExoPlayer
  • איך כוללים במדיה סשן מטא-נתונים של פריטים בתור ההפעלה
  • איך מוסיפים פעולות נוספות (בהתאמה אישית)

ב-Codelab הזה נתמקד ב-MediaSession SDK. מושגים ובלוקים של קוד שלא רלוונטיים, כולל פרטים על ההטמעה של ExoPlayer, לא מוצגים, אבל אתם יכולים פשוט להעתיק ולהדביק אותם.

מה תצטרכו

  • גרסה עדכנית של Android Studio (3.5 ואילך)
  • ידע בסיסי בפיתוח אפליקציות ל-Android

2. תהליך ההגדרה

מהי נקודת ההתחלה שלנו?

נקודת ההתחלה שלנו היא ההדגמה הראשית מ-ExoPlayer. הדמו הזה מכיל סרטונים עם אמצעי בקרה להפעלה במסך, אבל לא נעשה בו שימוש בסשנים של מדיה מחוץ לקופסה. זה מקום מצוין להתחיל בו ולהוסיף אותם!

קבלת דוגמה של ExoPlayer

כדי להתחיל בקלות, נתחיל עם דוגמה של ExoPlayer. משכפלים את מאגר GitHub על ידי הרצת הקוד שבהמשך.

git clone https://github.com/google/ExoPlayer.git

פתיחת ההדגמה

ב-Android Studio, פותחים את פרויקט ההדגמה הראשי שנמצא בתיקייה demos/main.

תופיע הנחיה ב-Android Studio להגדרת נתיב ה-SDK. אם נתקלים בבעיות, מומלץ לפעול לפי ההמלצות לעדכון כלי ה-IDE וה-SDK.

10e3b5c652186d57.png

אם מוצגת בקשה להשתמש בגרסת Gradle העדכנית, מעדכנים אותה.

כדאי להקדיש רגע כדי להבין איך האפליקציה בנויה. שימו לב שיש שתי פעילויות: SampleChooserActivity ו-PlayerActivity. במהלך שאר ה-codelab נתמקד ב-PlayerActivity, שבו המדיה מוצגת בפועל. לכן, פותחים את המחלקה הזו ועוברים לקטע הבא.

3. יצירת סשן מדיה וניהול הסטטוס שלו

יצירת סשן מדיה

פתיחת PlayerActivity.java. המחלקות האלה יוצרות את ExoPlayer ומנהלות את הפונקציות שלו, כמו עיבוד של סרטון להצגה במסך. בפעילות הזו, נקשר את ExoPlayer לסשן מדיה.

מצהירים על שני השדות הבאים בחלק העליון של המחלקה. נשתמש בשדות האלה לאורך כל הקטע הזה.

private MediaSessionCompat mediaSession;
private MediaSessionConnector mediaSessionConnector;

צריך להוסיף את התלות בפרויקט extension-mediasession אל build.gradle ברמת המודול של Module: demo:

implementation project(path: ':extension-mediasession')

שימו לב: Android Studio יכול לעזור לכם להוסיף את התלות הזו באופן אוטומטי אם מעבירים את העכבר מעל השגיאה שקשורה לפתרון MediaSessionConnector:

60055e4ad54fbb97.png

בסוף, מוסיפים את הפרטים הבאים כדי לפתור את בעיות הייבוא של הכיתות:

import android.support.v4.media.session.MediaSessionCompat;
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector;

כשיוצרים את הפעילות, צריך ליצור סשן מדיה ומחבר סשן מדיה שמשמש כמתווך בין סשן המדיה לבין ExoPlayer.

המיקום האידיאלי להוספת הקוד הזה הוא המקום שבו נוצר ExoPlayer. באפליקציית ההדגמה שלנו, אנחנו יכולים לצרף את הקוד שלנו לסוף של initializePlayer(). חשוב להוסיף את הלוגיקה הזו אחרי שמופעלת יצירת מופע של נגן!

private void initializePlayer() {
  if (player == null) {
    ...
    player = ...
    ...
    mediaSession = new MediaSessionCompat(this, "sample");
    mediaSessionConnector = new MediaSessionConnector(mediaSession);
    mediaSessionConnector.setPlayer(player);
  }
  ...
}

שחרור סשן המדיה

כשאין יותר צורך בסשן המדיה, צריך לשחרר אותו. כשנשיק את ExoPlayer ב-releasePlayer(), נוכל לכלול גם את הקוד הבא כדי לעשות זאת:

private void releasePlayer() {
  if (mediaSession != null) {
    mediaSession.release();
  }
  ...
}

ניהול מצב סשן המדיה

אחרי שיצרנו מופע של סשן המדיה, אנחנו צריכים לוודא שהמצב שלו משתקף בצורה נכונה כשהמשתמש מקיים אינטראקציה עם הפעילות.

כשהמשתמש מתחיל את הפעילות, סשן המדיה צריך להפוך לפעיל:

@Override
public void onStart() {
  ...
  if (mediaSession != null) {
    mediaSession.setActive(true);
  }
}

מכיוון שהאפליקציה שלנו לא מפעילה מדיה ברקע, חשוב לוודא שסשן המדיה הופך ללא פעיל כשהמשתמש יוצא מהפעילות:

@Override
public void onStop() {
  super.onStop();
  if (mediaSession != null) {
    mediaSession.setActive(false);
  }
  ...
}

הדגמה

  1. מצרפים מכשיר Android או מפעילים אמולטור.
  2. מוודאים שהאפשרות demo (הדגמה) נבחרה להפעלה מסרגל הכלים של Android Studio. cb1ec4e50886874f.png
  3. לוחצים על הסמל 9d8fb3a9ddf12827.png בסרגל הכלים של Android Studio.
  4. אחרי שהאפליקציה תיפתח במכשיר, בוחרים בשידור וידאו להפעלה.
  5. אחרי שההפעלה מתחילה, אפשר להשתמש בפקודות הבאות של adb כדי לשלוט בסשן המדיה:
adb shell media dispatch pause
adb shell media dispatch play
adb shell media dispatch play-pause
adb shell media dispatch fast-forward
adb shell media dispatch rewind
  1. כדאי גם לבדוק איך Android רואה את סשן המדיה. באופן ספציפי, אפשר לבדוק אילו פעולות נתמכות על ידי עיון בשדה הפעולה. המספר שמוצג כאן הוא שילוב של מזהי פעולות, כפי שהם מוצהרים באובייקט PlaybackState. כדי לראות את הפעלת סשן המדיה: adb shell dumpsys media_session
  2. אם אתם משתמשים במכשיר פיזי עם מיקרופון, נסו להפעיל את Google Assistant ולתת פקודות קוליות, כמו: "השהיה". ‏"Resume" ‫"Fast-forward 1 minute" ‏(הרצה קדימה של דקה אחת)

b8dda02a6fb0f6a4.png *דוגמה ל-ExoPlayer שפועל ב-Android TV.*

4. הוספת מטא-נתונים של פריטים לתור ההפעלה

עכשיו אפשר להרחיב את התכונות הנתמכות של סשן המדיה, שבו יצרנו בעבר את MediaSessionConnector ב-initializePlayer().

הוספת TimelineQueueNavigator

‫ExoPlayer מייצג את מבנה המדיה כציר זמן. כדי להבין איך זה עובד, כדאי לקרוא על אובייקט ציר הזמן של ExoPlayer. הודות למבנה הזה, אנחנו יכולים לקבל מידע על שינויים בתוכן ולחשוף את המטא-נתונים של מה שמופעל כרגע כשמבקשים.

כדי לעשות את זה, נגדיר TimelineQueueNavigator. מאתרים את יצירת המופע של MediaSessionConnector ב-initializePlayer() ומוסיפים הטמעה של TimelineQueueNavigator אחרי mediaSession.

mediaSessionConnector.setQueueNavigator(new TimelineQueueNavigator(mediaSession) {
  @Override
  public MediaDescriptionCompat getMediaDescription(Player player, int windowIndex) {
    return new MediaDescriptionCompat.Builder()
            .setTitle(player.getCurrentMediaItem().mediaMetadata.title)
            .setDescription("MediaDescription description for " + windowIndex)
            .setSubtitle("MediaDescription subtitle")
            .build();
  }
});

כדי לפתור את בעיות הייבוא של הכיתות, מוסיפים:

import android.support.v4.media.MediaDescriptionCompat;
import com.google.android.exoplayer2.ext.mediasession.TimelineQueueNavigator;

שימו לב שהפרמטר windowIndex תואם לפריט עם האינדקס הזה בתור ההפעלה.

אחרי שמוסיפים מטא-נתונים, אפשר לבדוק שה-Assistant מבין מה מושמע. כשמפעילים סרטון ב-Android TV, מפעילים את Assistant ושואלים "What's playing?‎" (מה מוצג?).

6c7fc0cb853cbc38.png

5. התאמה אישית של פעולות

יכול להיות שהנגן לא תומך בפעולות מסוימות, או שאתם רוצים לכלול תמיכה בפעולות נוספות. עכשיו נצלול קצת יותר לעומק של סשן המדיה שבו יצרנו קודם את MediaSessionConnector ב-initializePlayer().

הצהרה על פעולות נתמכות

אפשר להשתמש ב-mediaSessionConnector.setEnabledPlaybackActions() כדי להתאים אישית את הפעולות שרוצים שהסשן של המדיה יתמוך בהן.

שימו לב שהקבוצה המלאה היא:

mediaSessionConnector.setEnabledPlaybackActions(
        PlaybackStateCompat.ACTION_PLAY_PAUSE
                | PlaybackStateCompat.ACTION_PLAY
                | PlaybackStateCompat.ACTION_PAUSE
                | PlaybackStateCompat.ACTION_SEEK_TO
                | PlaybackStateCompat.ACTION_FAST_FORWARD
                | PlaybackStateCompat.ACTION_REWIND
                | PlaybackStateCompat.ACTION_STOP
                | PlaybackStateCompat.ACTION_SET_REPEAT_MODE
                | PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE
);

נראה שוב איך הנתונים האלה מוצגים בפלטפורמה:

  1. כמו קודם, מתחילים סרטון.
  2. כדי לראות איך מערכת Android מציגה את המטא-נתונים מסשן המדיה, מריצים את הפקודה: adb shell dumpsys media_session
  3. מאתרים את השורה שמכילה את המטא-נתונים ורואים שהשם והתיאור כלולים ומשויכים ל-com.google.android.exoplayer2.demo/sample.

הוספת פעולות נוספות

אפשר להוסיף עוד פעולות לסשן המדיה. בשלב הזה, אנחנו נוסיף תמיכה רק בכתוביות.

כתוביות תומכות

הוספת תמיכה בכתוביות להפעלת מדיה מאפשרת למשתמשים להפעיל או להשבית אותן באמצעות קול. במקום שבו הפעלתם את מחבר סשן המדיה, מוסיפים את הקוד הבא:

mediaSessionConnector.setCaptionCallback(new MediaSessionConnector.CaptionCallback() {
      @Override
      public void onSetCaptioningEnabled(Player player, boolean enabled) {
        Log.d("MediaSession", "onSetCaptioningEnabled: enabled=" + enabled);
      }

      @Override
      public boolean hasCaptions(Player player) {
        return true;
      }

      @Override
      public boolean onCommand(Player player, ControlDispatcher controlDispatcher, String command, Bundle extras, ResultReceiver cb) {
        return false;
      }
    }
);

לבסוף, מטפלים בייבוא חסר.

כדי לבדוק את זה, מפעילים את Google Assistant ב-Android TV ואומרים "הפעלת כתוביות". כדי לראות איך הקריאות האלה מתבצעות בקוד שלכם, בודקים את ההודעות ב-Logcat.

6. מזל טוב

כל הכבוד, הוספת בהצלחה סשנים של מדיה לדוגמה!

קיבלתם כמות עצומה של פונקציונליות באמצעות:

  • הוספת סשן מדיה,
  • קישור של סשנים של מדיה למופע של ExoPlayer,
  • הוספת מטא-נתונים ופעולות נוספות.

עכשיו אתם יודעים מהם השלבים העיקריים שצריך לבצע כדי להוסיף תכונות לאפליקציית מדיה ולהציע למשתמשים חוויה מגוונת יותר.

הערה סופית

שיעור ה-Codelab הזה מבוסס על דוגמה מקוד המקור של ExoPlayer. אין צורך להשתמש ב-ExoPlayer מהמקור, ומומלץ במקום זאת למשוך את התלות ב-ExoPlayer וב-MediaSessionConnector כדי שיהיה קל יותר להתעדכן בגרסאות האחרונות.

כדי לעשות את זה, פשוט מחליפים את התלות של הפרויקט, למשל:

implementation project(modulePrefix + 'library-core')
implementation project(path: ':extension-mediasession')

כדי לשלוף ממאגרי Maven, כמו:

implementation 'com.google.android.exoplayer:exoplayer-core:2.+'
implementation 'com.google.android.exoplayer:extension-mediasession:2.+'

מסמכי עזר