שיתוף קלט האודיו

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

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

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

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

התנהגות בגרסאות קודמות ל-Android 10

לפני Android 10, רק אפליקציה אחת בכל פעם יכלה להקליט את שידור האודיו של הקלט. אם אפליקציה אחרת כבר הקליטה או האזינה לאודיו, האפליקציה שלכם יכלה ליצור אובייקט AudioRecord, אבל הוחזרה שגיאה כשקראתם ל-AudioRecord.startRecording() וההקלטה לא התחילה.

היה יוצא דופן אחד לכלל הזה: כשאפליקציה עם הרשאות מיוחדות (כמו Google Assistant או שירות נגישות) קיבלה את ההרשאה android.permission.CAPTURE_AUDIO_HOTWORD והשתמשה במקור אודיו מסוג HOTWORD. במקרה כזה, אפליקציה אחרת יכולה להתחיל להקליט. במקרה כזה, האפליקציה עם ההרשאות נסגרה והאפליקציה החדשה קיבלה את הקלט.

ב-Android 9 נוסף עוד שינוי: רק אפליקציות שפועלות בחזית (או שירות שפועל בחזית) יכולות להקליט את קלט האודיו. כשאפליקציה בלי שירות שפועל בחזית או רכיב ממשק משתמש בחזית התחילה להקליט, היא המשיכה לפעול אבל הקליטה שקט, גם אם היא הייתה האפליקציה היחידה שהקליטה אודיו באותו זמן.

התנהגות ב-Android 10

ההתנהגות לפני Android 10 היא "כל הקודם זוכה". אחרי שאפליקציה מתחילה להקליט אודיו, אפליקציות אחרות לא יכולות לגשת לקלט האודיו עד שהאפליקציה שמקליטה אודיו מפסיקה.

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

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

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

  • אפליקציות "רגילות" מותקנות על ידי המשתמש.
  • אפליקציות "עם הרשאות" מותקנות מראש במכשיר. האפליקציות האלה כוללות את Google Assistant ואת כל שירותי הנגישות.

בנוסף, אפליקציה מטופלת באופן שונה אם היא משתמשת במקור אודיו "רגיש לפרטיות": CAMCORDER או VOICE_COMMUNICATION.

אלה כללי העדיפות לשימוש בקלט אודיו ולשיתוף שלו:

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

תרחישי שיתוף

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

יש ארבעה תרחישים עיקריים:

  • ‫Assistant + אפליקציה רגילה
  • שירות נגישות + אפליקציה רגילה
  • שתי אפליקציות רגילות
  • שיחת טלפון + אפליקציה רגילה

‫Assistant + אפליקציה רגילה

‫Assistant היא אפליקציה עם הרשאות מיוחדות כי היא מותקנת מראש ומוגדרת בתפקיד RoleManager.ROLE_ASSISTANT. כל אפליקציה אחרת שמותקנת מראש עם התפקיד הזה מטופלת באופן דומה.

מערכת Android משתפת את קלט האודיו לפי הכללים הבאים:

  • ‫Assistant יכולה לקבל אודיו (לא משנה אם היא פועלת בחזית או ברקע), אלא אם אפליקציה אחרת כבר מקליטה אודיו ממקור שרגיש לפרטיות.

  • האפליקציה מקבלת אודיו, אלא אם ל-Assistant יש רכיב ממשק משתמש גלוי בחלק העליון של המסך.

חשוב לזכור ששתי האפליקציות מקבלות אודיו רק כש-Assistant פועלת ברקע והאפליקציה השנייה לא מקליטה ממקור אודיו שרגיש לפרטיות.

שירות נגישות + אפליקציה רגילה

AccessibilityService דורש הצהרה מחמירה.

מערכת Android משתפת את קלט האודיו לפי הכללים הבאים:

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

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

שתי אפליקציות רגילות

כששתי אפליקציות מקליטות בו-זמנית, רק אחת מהן מקבלת אודיו והשנייה מקבלת שקט.

מערכת Android משתפת את קלט האודיו לפי הכללים הבאים:

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

שיחת טלפון + אפליקציה רגילה

שיחת טלפון פעילה אם מצב האודיו שמוחזר על ידי AudioManager.getMode() הוא MODE_IN_CALL או MODE_IN_COMMUNICATION.

מערכת Android משתפת את קלט האודיו לפי הכללים הבאים:

התנהגות ב-Android 11

ב-Android 11 (רמת API‏ 30) פועלת שיטת העדיפויות של Android 10 שמתוארת למעלה. הוא גם מספק שיטות חדשות ב-AudioRecord, ב-MediaRecorder וב-AAudioStream שמפעילות ומשביתות את היכולת להקליט אודיו בו-זמנית, בלי קשר לתרחיש לדוגמה שנבחר.

השיטות החדשות הן:

כשהערך של setPrivacySensitive() הוא true, תרחיש השימוש של ההקלטה הוא פרטי, ואפילו Assistant עם הרשאות לא יכולה להקליט בו-זמנית. ההגדרה הזו מבטלת את פעולת ברירת המחדל שתלויה במקור האודיו. לדוגמה, VOICE_COMMUNICATION הוא פרטי כברירת מחדל, אבל UNPROCESSED לא.

שינויים בהגדרות

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

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

אפליקציה פעילה עשויה להיות מושתקת כשאפליקציה עם עדיפות גבוהה יותר הופכת לפעילה. לכן, אתם יכולים לרשום AudioManager.AudioRecordingCallback באובייקט AudioRecord או MediaRecorder כדי לקבל התראה כשההגדרה משתנה. השינויים האפשריים:

  • הקלטה מושתקת או לא מושתקת
  • המכשיר השתנה
  • העיבוד המקדים השתנה
  • מאפייני הסטרימינג השתנו (תדירות הדגימה, מסכת הערוץ, פורמט הדגימה)

צריך להפעיל את AudioRecord.registerAudioRecordingCallback() לפני שמתחילים את התיעוד. הקריאה החוזרת מבוצעת רק כשהאפליקציה מקבלת אודיו ומתרחש שינוי.

השיטה onRecordingConfigChanged() מחזירה AudioRecordingConfiguration שמכיל את המצב הנוכחי של הקלטת האודיו. כדי לקבל מידע על השינוי, אפשר להשתמש בשיטות הבאות:

isClientSilenced()
הפונקציה מחזירה את הערך True אם האודיו שמוחזר ללקוח מושתק כרגע בגלל מדיניות ההקלטה.
getAudioDevice()
החזרת מכשיר האודיו הפעיל.
getEffects()
מחזירה את אפקט העיבוד המקדים הפעיל. שימו לב שהאפקט הפעיל לא בהכרח יהיה זהה לאלה שמוחזרים על ידי getClientEffects() אם הלקוח הוא לא האפליקציה הפעילה בעלת העדיפות הגבוהה ביותר.
getFormat()
הפונקציה מחזירה את מאפייני מקור הנתונים. חשוב לזכור שנתוני האודיו בפועל שהלקוח מקבל תמיד תואמים לפורמט הנדרש שמוחזר על ידי getClientFormat(). ה-framework מבצעת באופן אוטומטי את ההמרה הנדרשת של הדגימה מחדש, הערוץ והפורמט מהפורמט שבו נעשה שימוש בממשק החומרה לפורמט שצוין על ידי הלקוח.
AudioRecord.getActiveRecordingConfiguration()
הפונקציה מחזירה את הגדרת ההקלטה הפעילה.

כדי לקבל תצוגה כללית של כל ההקלטות הפעילות במכשיר, אפשר להפעיל את הפונקציה AudioManager.getActiveRecordingConfigurations().