שתי אפליקציות או יותר ל-Android יכולות להשמיע אודיו לאותו שידור פלט בו-זמנית, והמערכת תשלב הכול יחד. אומנם זה מרשים מבחינה טכנית, הוא עלול לפגוע במשתמש. כדי להימנע מכל שמופעלת בו-זמנית, Android מציג את הרעיון של אודיו מיקוד. אפשר לשמור את מיקוד האודיו רק באפליקציה אחת בכל פעם.
כשהאפליקציה צריכה להפיק אודיו, היא צריכה לבקש מיקוד אודיו. אחרי פוקוס, הוא יכול להשמיע צליל. עם זאת, אחרי שתסיימו להתמקד באודיו, יכול להיות שלא לשמור אותו עד לסיום המשחק. אפליקציה אחרת יכולה לבקש מיקוד, מכבה את האחיזה שלך בפוקוס אודיו. במקרה כזה, האפליקציה אמורה להשהות את האפליקציה מופעלת או מנמיכה את עוצמת הקול, כדי לאפשר למשתמשים לשמוע את מקור האודיו החדש בקלות רבה יותר.
לפני Android 12 (רמת API 31), מיקוד האודיו לא מנוהל על ידי המערכת. אז, אנחנו ממליצים למפתחי אפליקציות לציית להנחיות בנושא התמקדות באודיו, אם אפליקציה ממשיכה לפעול בעוצמה חזקה גם אחרי שהתמקדת באודיו במכשיר עם Android מגרסה 11 (רמת API 30) ומטה, המערכת לא יכולה למנוע זאת. עם זאת, התנהגות כזו באפליקציה מובילה לחוויית משתמש גרועה, ולרוב עלולה להוביל לחוויית משתמש גרועה להסיר את האפליקציה הבעייתית.
אפליקציית אודיו מעוצבת היטב צריכה לנהל את מיקוד האודיו לפי הכללים הבאים הנחיות:
צריך להתקשר אל
requestAudioFocus()
מיד לפני שמתחילים לשחק ולוודא השיחה מחזירהAUDIOFOCUS_REQUEST_GRANTED
. התקשרות אלrequestAudioFocus()
בקריאה החוזרת (callback) שלonPlay()
בסשן המדיה.כשאפליקציה אחרת מקבלת מיקוד אודיו, מפסיקים או משהים את ההפעלה, או כשאווז (כלומר, הפחתת עוצמת הקול.
כשההפעלה נעצרת (לדוגמה, אם לא נשאר שום דבר להפעיל באפליקציה), נוטשים את מיקוד האודיו. האפליקציה לא צריכה לבטל את מיקוד האודיו אם המשתמש משהה את ההפעלה, אבל יכול להיות שהוא ימשיך לפעול מאוחר יותר.
צריך להשתמש ב-
AudioAttributes
כדי לתאר סוג האודיו שהאפליקציה משמיעה. לדוגמה, באפליקציות שמשמיעות דיבור, לפרטCONTENT_TYPE_SPEECH
הטיפול בפוקוס האודיו משתנה בהתאם לגרסת Android שבה פועל:
- Android 12 (רמת API 31) ואילך
- המערכת מנהלת את מיקוד האודיו. המערכת מאלצת הפעלת אודיו למצב עמעום כשאפליקציה אחרת מבקשת מיקוד אודיו. המערכת גם השתקת האודיו כשמתקבלת שיחה נכנסת.
- Android 8.0 (רמת API 26) עד Android 11 (רמת API 30)
- מיקוד האודיו לא מנוהל על ידי המערכת, אבל כולל כמה שינויים הושקה החל מ-Android 8.0 (רמת API 26).
- Android 7.1 (רמת API 25) ומטה
- מיקוד האודיו לא מנוהל על ידי המערכת, ואפליקציות מנהלות את מיקוד האודיו באמצעות
requestAudioFocus()
וגםabandonAudioFocus()
.
מיקוד אודיו ב-Android מגרסה 12 ואילך
אם אפליקציית מדיה או אפליקציית משחקים שנעשה בה שימוש בפוקוס אודיו, לא אמור להפעיל אודיו אחרי שהמכשיר מאבד את המיקוד. להתמקד. בגרסה Android 12 (רמת API 31) ואילך, המערכת אוכפת את זה או התנהגות המשתמשים. כשאפליקציה מבקשת מיקוד אודיו בזמן שאפליקציה אחרת מתמקדת בפוקוס פועלת, המערכת מאלצת את האפליקציה המופעלת להיעלם. ההוספה של יציאה הדרגתית מאפשרת מעבר חלק יותר כשעוברים מאפליקציה אחת לאחרת.
ההתנהגות של יציאה הדרגתית מתרחשת כאשר התנאים הבאים מתקיימים:
האפליקציה הראשונה שמופעלת כרגע עומדת בכל הקריטריונים הבאים:
- באפליקציה יש את
AudioAttributes.USAGE_MEDIA
או מאפיין שימושAudioAttributes.USAGE_GAME
. - האפליקציה ביקשה להתמקד באודיו באמצעות
AudioManager.AUDIOFOCUS_GAIN
. - האפליקציה לא משמיעה אודיו עם סוג תוכן
AudioAttributes.CONTENT_TYPE_SPEECH
.
- באפליקציה יש את
אפליקציה נוספת מבקשת מיקוד אודיו באמצעות
AudioManager.AUDIOFOCUS_GAIN
.
כשהתנאים האלה מתקיימים, מערכת האודיו מפסיקה לפעול. ב של יציאה הדרגתית, המערכת מודיעה לאפליקציה הראשונה על אובדן מיקוד. של האפליקציה הנגנים יישארו מושתקים עד שהאפליקציה תבקש שוב מיקוד אודיו.
ההתנהגויות הקיימות של מיקוד אודיו
חשוב גם לשים לב למקרים אחרים שקשורים למעבר אודיו להתמקד.
הנמכה אוטומטית
הנמכה אוטומטית (הפחתה זמנית של רמת האודיו באפליקציה אחת), אחרת - אפשר לשמוע אותה בבירור) ב-Android 8.0 (רמת API 26).
בכך שהמערכת תטמיע 'הנמכה', אין צורך ליישם באפליקציה שלך.
'הנמכה אוטומטית' מתרחשת גם כשהתראות אודיו מושכות את המיקוד מאפליקציה שפועלת במכשיר. תחילת ההפעלה של ההתראה מסונכרנת בקצה רמפת הברווז.
התכונה 'הנמכה אוטומטית' מתרחשת כשהתנאים הבאים מתקיימים:
האפליקציה הראשונה שמופעלת כרגע עומדת בכל הקריטריונים הבאים:
- האפליקציה ביקשה מיקוד אודיו עם כל סוג של התמקדות רווח.
- האפליקציה לא משמיעה אודיו עם סוג תוכן
AudioAttributes.CONTENT_TYPE_SPEECH
- האפליקציה לא הוגדרה
AudioFocusRequest.Builder.setWillPauseWhenDucked(true)
אפליקציה נוספת מבקשת מיקוד אודיו באמצעות
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
כשהתנאים האלה מתקיימים, מערכת האודיו מכבה את כל הנגנים הפעילים האפליקציה הראשונה בזמן שהמיקוד באפליקציה השנייה. כשהאפליקציה השנייה נוטת את המיקוד, זה לא נותן להם את ה תשומת לב. האפליקציה הראשונה לא מקבלת התראה כשהיא מאבדת את המיקוד, כך שהוא לא צריך לעשות שום דבר.
לתשומת ליבכם: הנמכה אוטומטית לא מתבצעת כשהמשתמש מאזין של דיבור, מאחר שהמשתמש עלול לפספס חלק מהתוכנית. לדוגמה, ההנחייה הקולית לקבלת מסלול נסיעה אינה מוגנת.
השתקת האודיו הנוכחי בשיחות נכנסות
אפליקציות מסוימות לא פועלות כראוי וממשיכה להשמיע אודיו במהלך שיחות טלפון. המצב הזה מאלץ את המשתמש למצוא את האפליקציה הפוגענית, להשתיק אותה או לצאת ממנה כדי לשמוע את השיחה שלהם. כדי למנוע זאת, המערכת יכולה להשתיק אודיו ממקורות אחרים אפליקציות בזמן שיש שיחה נכנסת. המערכת מפעילה את התכונה הזו כאשר מתקבלת שיחת טלפון נכנסת, ואפליקציה שעומדת בתנאים הבאים:
- באפליקציה יש
AudioAttributes.USAGE_MEDIA
או מאפיין השימושAudioAttributes.USAGE_GAME
. - האפליקציה ביקשה מיקוד אודיו (כל שיפור מיקוד) והיא פועלת אודיו.
אם אפליקציה ממשיכה לפעול במהלך השיחה, ההפעלה מושתקת עד השיחה תסתיים. אבל אם אפליקציה מתחילה לפעול במהלך השיחה, השחקן לא מושתקת בהנחה שהמשתמש התחיל את ההפעלה באופן מכוון.
מיקוד האודיו במכשירי Android מגרסה 8.0 עד 11.
החל מ-Android 8.0 (רמת API 26), כשמבצעים קריאה
requestAudioFocus()
יש לספק פרמטר AudioFocusRequest
. AudioFocusRequest
מכיל מידע על הקשר האודיו ועל היכולות של האפליקציה.
המערכת משתמשת במידע הזה כדי לנהל את העלייה וההפסד של מיקוד האודיו
באופן אוטומטי. כדי לשחרר את מיקוד האודיו, צריך להפעיל את השיטה
abandonAudioFocusRequest()
שגם לוקח את AudioFocusRequest
כארגומנט. שימוש באותות
AudioFocusRequest
– גם כשמבקשים וגם נוטשים את המיקוד.
כדי ליצור AudioFocusRequest
, צריך להשתמש ב
AudioFocusRequest.Builder
מאחר שבקשת מיקוד
לציין תמיד את סוג הבקשה, הסוג כלול ב-constructor
ל-builder. משתמשים ב-methods של ה-build כדי להגדיר את השדות האחרים של ה-builder
בקשה.
השדה FocusGain
הוא חובה; כל שאר השדות הם אופציונליים.
שיטה | הערות |
---|---|
setFocusGain()
|
השדה הזה הוא חובה בכל בקשה. היא מקבלת את אותם הערכים כמו
הdurationHint ששימשה בשיחה אל requestAudioFocus() בגרסת טרום-Android 8.0:
AUDIOFOCUS_GAIN , AUDIOFOCUS_GAIN_TRANSIENT
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK או AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE .
|
setAudioAttributes()
|
AudioAttributes מתאר את התרחיש לדוגמה של האפליקציה שלך.
המערכת בודקת אותם כשאפליקציה צוברת או מאבדת את מיקוד האודיו. מאפיינים
תחליף את המונח 'סוג שידור'. בגרסה Android 8.0 (רמת API 26) ואילך,
סוגי סטרימינג לכל פעולה חוץ מפקדי עוצמת הקול הוצאו משימוש. כדאי להשתמש
אותם מאפיינים בבקשת המיקוד שבהם אתם משתמשים בנגן האודיו
שמוצגת בדוגמה שמופיעה אחרי הטבלה הזו).
צריך להשתמש ב-
אם לא מציינים את הפרמטר הזה, ברירת המחדל של |
setWillPauseWhenDucked()
|
כשאפליקציה אחרת מבקשת התמקדות באמצעות
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK , האפליקציה שהמיקוד בה לא
בדרך כלל מקבלים
onAudioFocusChange()
כי המערכת יכולה לבצע את
לשנות את עצמו. אם צריך להשהות את ההפעלה במקום זאת
במקום לשנות את עוצמת הקול, צריך לקרוא ל-setWillPauseWhenDucked(true) וליצור
OnAudioFocusChangeListener , כמו שמתואר בקטע פעולות אוטומטיות
"הנמכה".
|
setAcceptsDelayedFocusGain()
|
בקשה למיקוד אודיו עלולה להיכשל אם הפוקוס ננעל על ידי אפליקציה אחרת.
השיטה הזו מאפשרת להשיג עיכובים בפוקוס:
להשיג מיקוד באופן אסינכרוני כשהוא יהיה זמין.
שים לב: שיפור מיקוד מאוחר פועל רק אם מציינים גם
|
setOnAudioFocusChangeListener()
|
השדה OnAudioFocusChangeListener נדרש רק אם מציינים גם
willPauseWhenDucked(true) או setAcceptsDelayedFocusGain(true) בבקשה.
יש שתי שיטות להגדרת ה-listen: אחת עם ואחת בלי
של ה-handler. ה-handler הוא ה-thread שבו ה-listener רץ. אם
לא מציינים handler, את ה-handler שמשויך
נעשה שימוש ב- |
הדוגמה הבאה מראה איך להשתמש ב-AudioFocusRequest.Builder
כדי ליצור
AudioFocusRequest
ולבקש נטישה של מיקוד האודיו:
Kotlin
// initializing variables for audio focus and playback management audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager focusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).run { setAudioAttributes(AudioAttributes.Builder().run { setUsage(AudioAttributes.USAGE_GAME) setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) build() }) setAcceptsDelayedFocusGain(true) setOnAudioFocusChangeListener(afChangeListener, handler) build() } val focusLock = Any() var playbackDelayed = false var playbackNowAuthorized = false // requesting audio focus and processing the response val res = audioManager.requestAudioFocus(focusRequest) synchronized(focusLock) { playbackNowAuthorized = when (res) { AudioManager.AUDIOFOCUS_REQUEST_FAILED -> false AudioManager.AUDIOFOCUS_REQUEST_GRANTED -> { playbackNow() true } AudioManager.AUDIOFOCUS_REQUEST_DELAYED -> { playbackDelayed = true false } else -> false } } // implementing OnAudioFocusChangeListener to react to focus changes override fun onAudioFocusChange(focusChange: Int) { when (focusChange) { AudioManager.AUDIOFOCUS_GAIN -> if (playbackDelayed || resumeOnFocusGain) { synchronized(focusLock) { playbackDelayed = false resumeOnFocusGain = false } playbackNow() } AudioManager.AUDIOFOCUS_LOSS -> { synchronized(focusLock) { resumeOnFocusGain = false playbackDelayed = false } pausePlayback() } AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> { synchronized(focusLock) { // only resume if playback is being interrupted resumeOnFocusGain = isPlaying() playbackDelayed = false } pausePlayback() } AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> { // ... pausing or ducking depends on your app } } }
Java
// initializing variables for audio focus and playback management audioManager = (AudioManager) Context.getSystemService(Context.AUDIO_SERVICE); playbackAttributes = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_GAME) .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .build(); focusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN) .setAudioAttributes(playbackAttributes) .setAcceptsDelayedFocusGain(true) .setOnAudioFocusChangeListener(afChangeListener, handler) .build(); final Object focusLock = new Object(); boolean playbackDelayed = false; boolean playbackNowAuthorized = false; // requesting audio focus and processing the response int res = audioManager.requestAudioFocus(focusRequest); synchronized(focusLock) { if (res == AudioManager.AUDIOFOCUS_REQUEST_FAILED) { playbackNowAuthorized = false; } else if (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { playbackNowAuthorized = true; playbackNow(); } else if (res == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) { playbackDelayed = true; playbackNowAuthorized = false; } } // implementing OnAudioFocusChangeListener to react to focus changes @Override public void onAudioFocusChange(int focusChange) { switch (focusChange) { case AudioManager.AUDIOFOCUS_GAIN: if (playbackDelayed || resumeOnFocusGain) { synchronized(focusLock) { playbackDelayed = false; resumeOnFocusGain = false; } playbackNow(); } break; case AudioManager.AUDIOFOCUS_LOSS: synchronized(focusLock) { resumeOnFocusGain = false; playbackDelayed = false; } pausePlayback(); break; case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: synchronized(focusLock) { // only resume if playback is being interrupted resumeOnFocusGain = isPlaying(); playbackDelayed = false; } pausePlayback(); break; case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: // ... pausing or ducking depends on your app break; } } }
הנמכה אוטומטית
ב-Android 8.0 (רמת API 26), כשאפליקציה אחרת מתמקדת ב-
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
המערכת יכולה לשנות את עוצמת הקול ולשחזר אותה
בלי להפעיל את הקריאה החוזרת (callback) של האפליקציה onAudioFocusChange()
.
בעוד ש'הנמכה אוטומטית' היא התנהגות מקובלת בהפעלה של מוזיקה וסרטונים אפליקציות, הן לא שימושיות כשמפעילים תוכן שמוקרא בקול, למשל באפליקציה של ספר אודיו. במקרה כזה, צריך להשהות את האפליקציה במקום זאת.
אם רוצים שהאפליקציה תושהה כשמוצגת בקשה להנמיך את עוצמת הקול במקום להנמיך את עוצמת הקול, צריך ליצור OnAudioFocusChangeListener
עם
שיטת קריאה חוזרת (callback) מסוג onAudioFocusChange()
שמממשת את התנהגות ההשהיה/ההמשך הרצויה.
התקשרו אל setOnAudioFocusChangeListener()
כדי לרשום את המאזינים והתקשרו
setWillPauseWhenDucked(true)
כדי להורות למערכת להשתמש בקריאה חוזרת (callback) במקום לבצע 'הנמכה אוטומטית' אוטומטית.
עיכוב בניצול הפוקוס
לפעמים המערכת לא יכולה לאשר בקשה למיקוד אודיו כי המיקוד
'נעול' באמצעות אפליקציה אחרת, למשל במהלך שיחת טלפון. במקרה הזה,
הפונקציה requestAudioFocus()
מחזירה AUDIOFOCUS_REQUEST_FAILED
. במקרה כזה,
האפליקציה לא אמורה להמשיך בהפעלת אודיו כי היא לא הצליחה
להתמקד.
השיטה setAcceptsDelayedFocusGain(true)
שמאפשרת לאפליקציה לטפל בבקשה למיקוד
באופן אסינכרוני. כאשר הדגלים האלה מוגדרים, בקשה נשלחת כשהמיקוד נעול
הפונקציה מחזירה את הערך AUDIOFOCUS_REQUEST_DELAYED
. כשהתנאי לנעילת האודיו
לדוגמה, כששיחת טלפון מסתיימת, המערכת
מעניק את הבקשה למיקוד שבהמתנה ומתקשר אל onAudioFocusChange()
כדי להודיע
אפליקציה.
כדי להתמודד עם עיכוב בפוקוס, צריך ליצור
OnAudioFocusChangeListener
עם שיטת קריאה חוזרת (callback) מסוג onAudioFocusChange()
מיישמים את ההתנהגות הרצויה ורושמים את המאזינים באמצעות קריאה
setOnAudioFocusChangeListener()
.
מיקוד אודיו ב-Android 7.1 ומטה
כשמתקשרים
requestAudioFocus()
עליך לציין רמז למשך זמן,
מכבדת על ידי אפליקציה אחרת שנמצאת כרגע במוקד ההתעניינות וממשיכים לפעול:
- צריך לבקש מיקוד אודיו קבוע (
AUDIOFOCUS_GAIN
) כשמתכננים להפעיל אודיו בעתיד הקרוב (למשל, כשמשמיעים מוזיקה) ואתה מצפה הבעלים הקודם של מיקוד האודיו כדי להפסיק את ההפעלה. - בקשת מיקוד זמני (
AUDIOFOCUS_GAIN_TRANSIENT
) בזמן המשחק את האודיו לזמן קצר בלבד, ואתם מצפים שהמשתמש הקודם ישהה מתבצעת הפעלה. - בקשת מיקוד זמני באמצעות הנמכה (ducking)
(
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
) כדי לציין שציפית להשמיע אודיו לזמן קצר בלבד, ושבעלי המוקד הקודם יוכלו לשמור ואם זה 'רווז', (נמוך) פלט האודיו שלו. שני פלטי האודיו מעורבים לשידור האודיו. הנמכה מתאימה במיוחד לאפליקציות שמשתמשות שידור אודיו לסירוגין, למשל כדי להשמיע הוראות נסיעה.
השיטה requestAudioFocus()
מחייבת AudioManager.OnAudioFocusChangeListener
. המאזינים האלה צריכים להיות
שנוצרו באותה פעילות או בשירות שבבעלותו סשן המדיה שלכם הוא הבעלים. הוא
מטמיעים את הקריאה החוזרת onAudioFocusChange()
שהאפליקציה מקבלת
אפליקציה אחרת מסוימת מקבלת או נוטת את מיקוד האודיו.
קטע הקוד הבא מבקש מיקוד אודיו קבוע בשידור
STREAM_MUSIC
ורישום OnAudioFocusChangeListener
לטיפול
בשינויים הבאים בפוקוס האודיו. (ההסבר על השינוי מתקיים
תגובה לשינוי במוקד האודיו.)
Kotlin
audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager lateinit var afChangeListener AudioManager.OnAudioFocusChangeListener ... // Request audio focus for playback val result: Int = audioManager.requestAudioFocus( afChangeListener, // Use the music stream. AudioManager.STREAM_MUSIC, // Request permanent focus. AudioManager.AUDIOFOCUS_GAIN ) if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { // Start playback }
Java
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); AudioManager.OnAudioFocusChangeListener afChangeListener; ... // Request audio focus for playback int result = audioManager.requestAudioFocus(afChangeListener, // Use the music stream. AudioManager.STREAM_MUSIC, // Request permanent focus. AudioManager.AUDIOFOCUS_GAIN); if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { // Start playback }
בסיום ההפעלה, ניתן להתקשר
abandonAudioFocus()
Kotlin
audioManager.abandonAudioFocus(afChangeListener)
Java
// Abandon audio focus when playback complete audioManager.abandonAudioFocus(afChangeListener);
פעולה זו תיידע את המערכת שאין לך יותר צורך בפוקוס ותבטל את הרישום של
המשויך OnAudioFocusChangeListener
. אם ביקשתם מיקוד זמני,
פעולה זו תיידע אפליקציה שנמצאת בהשהיה או במצב התקינה והיא עשויה להמשיך לפעול או
לשחזר את עוצמת הקול שלו.
תגובה לשינוי של מיקוד האודיו
כשאפליקציה מוגדרת למיקוד אודיו, היא צריכה להיות מסוגלת לשחרר את הבחירה כשאפליקציה אחרת
מבקש להתמקד באודיו בעצמו. במקרה כזה, האפליקציה
מקבל קריאה
onAudioFocusChange()
ב-AudioFocusChangeListener
שציינת כשהאפליקציה נקראת requestAudioFocus()
.
הפרמטר focusChange
שהועבר אל onAudioFocusChange()
מציין את הסוג
של השינוי שמתרחש. הוא תואם
לרמז למשך הזמן שהאפליקציה מקבלת את המיקוד. האפליקציה שלך צריכה
להגיב בצורה הולמת.
- אובדן מיקוד זמני
-
אם שינוי המיקוד הוא זמני (
AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
אוAUDIOFOCUS_LOSS_TRANSIENT
), האפליקציה אמורה להתייעל (אם לא מסתמכים על נתונים כאלה בהנמכה אוטומטית) או להשהות את ההפעלה, אחרת יישארו על אותו מצב.כאשר המיקוד באודיו אבד זמנית, יש להמשיך לעקוב אחר השינויים בפוקוס אודיו, ויהיה מוכן להמשיך בהפעלה הרגילה לאחר שתחזירו את להתמקד. כשהאפליקציה החוסמת מפסיקה את המיקוד, מקבלים קריאה חוזרת (
AUDIOFOCUS_GAIN
). בשלב הזה תוכלו לשחזר את עוצמת הקול לרמה הרגילה או להפעיל מחדש את ההפעלה. - אובדן מיקוד תמידי
-
אם המיקוד של האודיו נעלם באופן סופי (
AUDIOFOCUS_LOSS
), אפליקציה אחרת מושמע אודיו. האפליקציה צריכה להשהות את ההפעלה באופן מיידי, כי היא אף פעם לא קבלת קריאה חוזרת (callback) שלAUDIOFOCUS_GAIN
. כדי להפעיל מחדש את ההפעלה, המשתמש חייבת לבצע פעולה מפורשת, כמו לחיצה על לחצן ההעברות של Play בהתראות או בממשק משתמש של אפליקציה.
קטע הקוד הבא מדגים איך להטמיע את
OnAudioFocusChangeListener
והקריאה החוזרת שלו onAudioFocusChange()
. שימו לב ל
שימוש ב-Handler
כדי לעכב את עצירת הקריאה החוזרת במקרה של אובדן אודיו לתמיד
להתמקד.
Kotlin
private val handler = Handler() private val afChangeListener = AudioManager.OnAudioFocusChangeListener { focusChange -> when (focusChange) { AudioManager.AUDIOFOCUS_LOSS -> { // Permanent loss of audio focus // Pause playback immediately mediaController.transportControls.pause() // Wait 30 seconds before stopping playback handler.postDelayed(delayedStopRunnable, TimeUnit.SECONDS.toMillis(30)) } AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> { // Pause playback } AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> { // Lower the volume, keep playing } AudioManager.AUDIOFOCUS_GAIN -> { // Your app has been granted audio focus again // Raise volume to normal, restart playback if necessary } } }
Java
private Handler handler = new Handler(); AudioManager.OnAudioFocusChangeListener afChangeListener = new AudioManager.OnAudioFocusChangeListener() { public void onAudioFocusChange(int focusChange) { if (focusChange == AudioManager.AUDIOFOCUS_LOSS) { // Permanent loss of audio focus // Pause playback immediately mediaController.getTransportControls().pause(); // Wait 30 seconds before stopping playback handler.postDelayed(delayedStopRunnable, TimeUnit.SECONDS.toMillis(30)); } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) { // Pause playback } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) { // Lower the volume, keep playing } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) { // Your app has been granted audio focus again // Raise volume to normal, restart playback if necessary } } };
ה-handler משתמש ב-Runnable
שנראה כך:
Kotlin
private var delayedStopRunnable = Runnable { mediaController.transportControls.stop() }
Java
private Runnable delayedStopRunnable = new Runnable() { @Override public void run() { getMediaController().getTransportControls().stop(); } };
כדי לוודא שהעצירה המתוזמנת לא תיכנס לתוקף אם המשתמש יפעיל מחדש את ההפעלה, צריך לבצע קריאה
mHandler.removeCallbacks(mDelayedStopRunnable)
בתגובה לכל מצב
שינויים. לדוגמה, צריך להפעיל את המספר removeCallbacks()
במספר onPlay()
של הקריאה החוזרת.
onSkipToNext()
וכו'. עליך לקרוא לשיטה הזו גם
onDestroy()
קריאה חוזרת (callback) כשמנקים את המשאבים שמשמשים את השירות.