לחצני מדיה הם לחצני חומרה שקיימים במכשירי Android ובציוד היקפי אחר. למשל, לחצן ההשהיה/הפעלה באוזניות Bluetooth. כשמשתמש לוחץ על לחצן מדיה, מערכת Android יוצרת KeyEvent
, שמכיל קוד מפתח שמזהה את הלחצן. קודי המפתח של לחצני מדיה הם קבועים שמתחילים ב-KEYCODE_MEDIA
(לדוגמה, KEYCODE_MEDIA_PLAY
).
צריכה להיות לאפליקציות אפשרות לטפל באירועים של לחצני מדיה בשלושה מקרים, בסדר הזה של עדיפות:
- מתי הפעילות של ממשק המשתמש של האפליקציה גלויה
- כאשר הפעילות בממשק המשתמש מוסתרת וסשן המדיה של האפליקציה פעיל
- כשהפעילות בממשק המשתמש מוסתרת וסשן המדיה של האפליקציה לא פעיל וצריך להפעיל אותו מחדש
טיפול בלחצני מדיה בפעילות בחזית
הפעילות בחזית מקבלת את האירוע המרכזי של לחצן המדיה ב-onKeyDown()
שלה
. בהתאם לגרסה שפועלת של Android, יש שתי דרכים שבהן המערכת מנתבת את האירוע אל
בקר מדיה:
- אם במכשיר פועלת מערכת Android בגרסה 5.0 (רמת API 21) ואילך, יש להתקשר
FLAG_HANDLES_MEDIA_BUTTONS
MediaBrowserCompat.ConnectionCallback.onConnected
. הפעולה הזו תגרור תיקרא באופן אוטומטיdispatchMediaButtonEvent()
, שמתרגם את קוד המפתח לקריאה חוזרת (callback) בסשן מדיה. - לפני Android 5.0 (רמת API 21), עליך לשנות את
onKeyDown()
כדי שיטפל ב- לאירוע בעצמכם. (אפשר לקרוא פרטים נוספים במאמר טיפול בלחצני מדיה בסשן פעיל במדיה). קטע הקוד הבא מראה איך לעצור את קוד מפתח וקריאה ל-dispatchMediaButtonEvent(). חשוב להחזיר אתtrue
אל מציין שהאירוע טופל:Kotlin
fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { return super.onKeyDown(keyCode, event) } when (keyCode) { KeyEvent.KEYCODE_MEDIA_PLAY -> { yourMediaController.dispatchMediaButtonEvent(event) return true } } return super.onKeyDown(keyCode, event) }
Java
@Override boolean onKeyDown(int keyCode, KeyEvent event) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { return super.onKeyDown(keyCode, event); } switch (keyCode) { case KeyEvent.KEYCODE_MEDIA_PLAY: yourMediaController.dispatchMediaButtonEvent(event); return true; } return super.onKeyDown(keyCode, event); }
איתור סשן מדיה
אם הפעילות בחזית לא מטפלת באירוע, מערכת Android תנסה למצוא סשן מדיה שמסוגל להתמודד איתם. שוב, בהתאם לגרסה שפועלת ב-Android, יש שתי דרכים לחפש סשן מדיה:
אם במכשיר פועלת מערכת Android בגרסה 8.0 (רמת API 26) ואילך, המערכת תנסה מוצאים את האפליקציה האחרונה באמצעות MediaSession שהופעלה אודיו באופן מקומי. אם הסשן עדיין פעיל, מערכת Android שולחת את האירוע ישירות אליו. אחרת, אם הסשן לא פעיל ויש בו מקלט מדיה, מערכת Android שולחת את האירוע של המקבל, שיפעיל מחדש את הסשן כדי שהוא יוכל לקבל את האירוע. (פרטים נוספים זמינים במאמר שימוש בלחצני מדיה כדי להפעיל מחדש סשן מדיה לא פעיל). אם אין בסשן מקלט של לחצני מדיה, המערכת מוחקת את המדיה אירוע של לחצן ושום דבר לא יקרה. הלוגיקה הזו מוצגת דיאגרמה:
לפני Android 8.0 (רמת API 26), המערכת תנסה לשלוח את האירוע סשן מדיה פעיל. אם יש כמה סשנים פעילים של מדיה, מערכת Android תנסה כדי לבחור סשן מדיה שמתכונן להפעלה (אגירת נתונים/התחברות), שמופעלת או מושהית, במקום להשתמש בסרטון שנעצר. (ראו טיפול בלחצני מדיה בסשן מדיה פעיל לקבלת פרטים נוספים). אם אין אף גרסה פעילה סשן, מערכת Android תנסה לשלוח את האירוע לסשן האחרון שהיה פעיל. (פרטים נוספים זמינים במאמר שימוש בלחצני מדיה כדי להפעיל מחדש סשן מדיה לא פעיל). הלוגיקה מוצגת בתרשים הבא:
טיפול בלחצני מדיה בסשן מדיה פעיל
ב-Android מגרסה 5.0 (רמת API 21) ואילך, מערכת Android שולחת אירועים של לחצני מדיה באופן אוטומטי לסשן המדיה הפעיל שלך, באמצעות התקשרות
onMediaButtonEvent()
כברירת מחדל, הקריאה החוזרת (callback) הזו מתרגמת את KeyEvent לשיטת הקריאה החוזרת (callback) המתאימה של סשן המדיה שתואמת לקוד המפתח.
לפני Android 5.0 (רמת API 21), Android מטפל באירועים של לחצני מדיה על ידי שידור כוונה
עם הפעולה ACTION_MEDIA_BUTTON
. האפליקציה שלך צריכה לרשום
BroadcastReceiver במטרה ליירט את הכוונות האלה.
MediaButtonReceiver
תוכנן במיוחד
למטרה הזאת. זהו רמת נוחות
ב-Android
תואם למדיה
מטפל ב-ACTION_MEDIA_BUTTON
ומתרגם את ה-Intents הנכנסים
קריאות מתאימות של שיטת MediaSessionCompat.Callback
.
MediaButtonReceiver
הוא שירות BroadcastReceiver לטווח קצר. היא מעבירה הודעות נכנסות
כוונות לשירות שמנהל את סשן המדיה שלכם. אם רוצים להשתמש
לחצני מדיה במערכות שקודמות ל-Android 5.0, חובה לכלול
את ה-MediaButtonReceiver
במניפסט עם מסנן Intent מסוג MEDIA_BUTTON
.:
<receiver android:name="android.support.v4.media.session.MediaButtonReceiver" >
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
ה-BroadcastReceiver
מעביר את הכוונה לשירות שלכם. כדי לנתח את הכוונה
ויוצרים את הקריאה החוזרת לסשן המדיה, כוללים את השיטה MediaButtonReceiver.handleIntent()
ב-onStartCommand()
של השירות.
הפעולה הזו מתרגמת את קוד המפתח לשיטת הקריאה החוזרת (callback) המתאימה לסשן.
Kotlin
private val mediaSessionCompat: MediaSessionCompat = ... override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { MediaButtonReceiver.handleIntent(mediaSessionCompat, intent) return super.onStartCommand(intent, flags, startId) }
Java
private MediaSessionCompat mediaSessionCompat = ...; public int onStartCommand(Intent intent, int flags, int startId) { MediaButtonReceiver.handleIntent(mediaSessionCompat, intent); return super.onStartCommand(intent, flags, startId); }
שימוש בלחצני מדיה כדי להפעיל מחדש סשן מדיה לא פעיל
אם מערכת Android מזהה את סשן המדיה הפעיל האחרון, היא מנסה להתחיל מחדש את הסשן על ידי שליחת Intent מסוג ACTION_MEDIA_BUTTON
לרכיב שרשום במניפסט (כמו שירות או BroadcastReceiver
).
כך האפליקציה יכולה להפעיל מחדש את ההפעלה כשממשק המשתמש שלה לא גלוי. המצב הזה קורה ברוב אפליקציות האודיו.
ההתנהגות הזו מופעלת באופן אוטומטי כשמשתמשים ב-MediaSessionCompat
. אם
להשתמש ב-MediaSession
של מסגרת Android או בספריית התמיכה בגרסה 24.0.0 עד
25.1.1 צריך להתקשר ל-setMediaButtonReceiver
כדי לאפשר ללחצן מדיה להפעיל מחדש
סשן מדיה לא פעיל.
ניתן להשבית את ההתנהגות הזו ב-Android 5.0 (רמת API 21) ואילך על ידי הגדרת מקלט של לחצן מדיה ריק:
Kotlin
// Create a MediaSessionCompat mediaSession = MediaSessionCompat(context, LOG_TAG) mediaSession.setMediaButtonReceiver(null)
Java
// Create a MediaSessionCompat mediaSession = new MediaSessionCompat(context, LOG_TAG); mediaSession.setMediaButtonReceiver(null);
התאמה אישית של רכיבי ה-handler של לחצני המדיה
פעולת ברירת המחדל של onMediaButtonEvent()
שולפת את קוד המפתח ומשתמשת במצב הנוכחי של סשן המדיה וברשימת הפעולות הנתמכות כדי לקבוע לאיזו שיטה להפעיל. לדוגמה, KEYCODE_MEDIA_PLAY
מפעיל את onPlay()
.
כדי לספק חוויה עקבית של לחצני המדיה בכל האפליקציות, צריך להשתמש
את התנהגות ברירת המחדל וסטייה רק למטרה ספציפית. אם לחצן מדיה
נדרשת טיפול מותאם אישית, יש לבטל את הקריאה החוזרת
onMediaButtonEvent()
מחלצים את KeyEvent
באמצעות
intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT)
,
לטפל באירוע בעצמך ולהחזיר את הקובץ true
.
סיכום
כדי לטפל כראוי באירועים של לחצני מדיה בכל הגרסאות של Android, צריך
ציון FLAG_HANDLES_MEDIA_BUTTONS
כשיוצרים סשן מדיה.
בנוסף, בהתאם לגרסאות Android שבהן אתם מתכוונים לתמוך, צריך לעמוד גם בדרישות הבאות:
בהפעלה ב-Android מגרסה 5.0 ואילך:
- התקשרות חזרה אל
MediaControllerCompat.setMediaController()
מבקר המדיהonConnected()
- כדי לאפשר ללחצן מדיה להפעיל מחדש סשן לא פעיל, צריך ליצור באופן דינמי
MediaButtonReceiver
באמצעות התקשרותsetMediaButtonReceiver()
ולהעביר אותהPendingIntent
בהפעלה במערכות שקודמות ל-Android 5.0:
- כדי לטפל בלחצני מדיה, צריך לשנות את
onKeyDown()
של הפעילות - יצירה סטטית של
MediaButtonReceiver
על ידי הוספתו למניפסט של האפליקציה