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. אם נתקלים בבעיות, מומלץ לפעול לפי ההמלצות לעדכון כלי ה-SDK וסביבת הפיתוח המשולבת (IDE).

אם תתבקשו להשתמש בגרסת 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:

לבסוף, פותרים את בעיות הייבוא של הכיתות על ידי הוספת הפרטים הבאים:
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);
}
...
}
הדגמה
- מצרפים מכשיר Android או מפעילים אמולטור.
- מוודאים שהאפשרות demo (הדגמה) נבחרה להפעלה מסרגל הכלים של Android Studio.

- לוחצים על הסמל
בסרגל הכלים של Android Studio. - אחרי שהאפליקציה מופעלת במכשיר, בוחרים בסטרימינג של סרטון להפעלה.
- אחרי שההפעלה מתחילה, אפשר להשתמש בפקודות הבאות של
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
- כדאי גם לבדוק איך Android רואה את סשן המדיה. באופן ספציפי, אפשר לבדוק אילו פעולות נתמכות על ידי עיון בשדה הפעולה. המספר שמוצג כאן הוא שילוב של מזהי פעולות, כפי שהם מוצהרים באובייקט PlaybackState. כדי לראות את הפעלת סשן המדיה:
adb shell dumpsys media_session - אם אתם משתמשים במכשיר פיזי עם מיקרופון, נסו להפעיל את Google Assistant ולתת פקודות קוליות, כמו: 'השהיה'. "Resume" "Fast-forward 1 minute" (הרצה קדימה של דקה אחת).
דוגמה ל-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?" (מה מופעל?).

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
);
נראה שוב איך הנתונים האלה מוצגים בפלטפורמה:
- כמו קודם, מתחילים סרטון.
- כדי לראות איך מערכת Android מציגה את המטא-נתונים מסשן המדיה, מריצים את הפקודה:
adb shell dumpsys media_session - מאתרים את השורה שמכילה את המטא-נתונים ורואים שהכותרת והתיאור כלולים ומשויכים ל-
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.+'