קלט האודיו מגיע בדרך כלל מהמיקרופון המובנה, ממיקרופון חיצוני או מממשק אודיו שמחובר למכשיר. קלט אודיו יכול להגיע גם משיחה בטלפון.
לפעמים ייתכן ששתי אפליקציות או יותר מבקשות את אותו קלט אודיו. יכול להיות שהם מבצעים משימות שונות. לדוגמה, אפליקציות מסוימות שמקבלות אודיו עשויות "להקליט", כמו מכשיר הקלטה פשוט, ואפליקציות אחרות יכולות "להאזין", כמו 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 משתף את אודיו הקלט לפי הכללים הבאים:
- השיחה תמיד מקבלת אודיו.
- האפליקציה יכולה לתעד אודיו אם היא שירות נגישות.
האפליקציה יכולה לתעד את השיחה הקולית אם היא אפליקציה בעלת הרשאות (שהותקנה מראש) עם ההרשאה
CAPTURE_AUDIO_OUTPUT
.כדי לתעד את ה-uplink (TX) או ה-downlink (RX) של שיחת הקול, או את שניהם, האפליקציה צריכה לציין את מקורות האודיו
MediaRecorder.AudioSource.VOICE_UPLINK
אוMediaRecorder.AudioSource.VOICE_DOWNLINK
, ו/או את המכשירAudioDeviceInfo.TYPE_TELEPHONY
.
ההתנהגות ב-Android 11
מערכת Android 11 (רמת API 30) בודקת את סכימת העדיפות של Android 10 שמתוארת למעלה. הוא גם מספק שיטות חדשות ב-AudioRecord
, ב-MediaRecorder
וב-AAudioStream
, שמאפשרות ומשביתים את האפשרות להקליט אודיו בו-זמנית, בלי קשר לתרחיש לדוגמה שנבחר.
אלה השיטות החדשות:
AudioRecord.Builder.setPrivacySensitive()
AudioRecord.isPrivacySensitive()
MediaRecorder.setPrivacySensitive()
MediaRecorder.isPrivacySensitive()
AAudioStreamBuilder_setPrivacySensitive()
AAudioStream_isPrivacySensitive()
כשהערך של setPrivacySensitive()
הוא true
, תרחיש השימוש בצילום הוא פרטי ואפילו Assistant עם הרשאות לא יכולה לצלם בו-זמנית. ההגדרה הזאת מבטלת את
התנהגות ברירת המחדל שתלויה במקור האודיו. לדוגמה, כברירת מחדל, VOICE_COMMUNICATION
הוא פרטי אבל UNPROCESSED
לא.
שינויים בהגדרות
כשמספר אפליקציות מתעדות אודיו בו-זמנית, רק אחת או שתיים מהן הן 'פעילות' (מקבלות אודיו). שאר האפליקציות מושתקות (מקבלות שתיקה). כשהאפליקציות הפעילות משתנות, מסגרת האודיו עשויה להגדיר מחדש את נתיבי האודיו בהתאם לכללים הבאים:
- ייתכן שמכשיר קלט האודיו של כל אפליקציה פעילה ישתנה (לדוגמה, מהמיקרופון המובנה לאוזניות Bluetooth מחוברות).
- העיבוד המקדים שמשויך לאפליקציה הפעילה עם העדיפות הגבוהה ביותר מופעל. המערכת מתעלמת מכל עיבוד מקדים אחר.
אפליקציה פעילה עשויה להיות מושתקת כשאפליקציה בעדיפות גבוהה יותר הופכת לפעילה, ולכן אפשר לרשום
AudioManager.AudioRecordingCallback באובייקט AudioRecord
או MediaRecorder
כדי לקבל התראה על שינויים בהגדרה.
השינויים האפשריים יכולים להיות:
- צילום במצב מושתק או לא מושתק
- המכשיר השתנה
- העיבוד מראש השתנה
- מאפייני הסטרימינג השתנו (קצב דגימה, מסכת ערוץ, פורמט דגימה)
צריך לבצע קריאה ל-AudioRecord.registerAudioRecordingCallback()
לפני שמתחילים את הצילום.
הקריאה החוזרת מבוצעת רק כשהאפליקציה מקבלת אודיו ומתרחשים שינויים.
השיטה onRecordingConfigChanged()
מחזירה AudioRecordingConfiguration
את המצב הנוכחי של הקלטת האודיו. אפשר להיעזר בשיטות הבאות כדי לקבל מידע על השינוי:
isClientSilenced()
- הפונקציה מחזירה את הערך True אם האודיו שהוחזר ללקוח מושתק כרגע בגלל מדיניות הצילום.
getAudioDevice()
- החזרת מכשיר האודיו הפעיל.
getEffects()
- מחזירה את אפקט העיבוד המקדים הפעיל. שימו לב: יכול להיות שהאפקט הפעיל לא יהיה זהה לאפקטים שמוחזרים על ידי
getClientEffects()
אם הלקוח הוא לא האפליקציה הפעילה עם העדיפות הגבוהה ביותר. getFormat()
- מחזירה את מאפייני מקור הנתונים. שימו לב שנתוני האודיו בפועל שהלקוח מקבל תמיד תואמים לפורמט הנדרש שמוחזרים על ידי
getClientFormat()
. המסגרת מבצעת באופן אוטומטי את ההמרות הנדרשות של הדגימה מחדש, הערוץ והפורמט מהפורמט שבו נעשה שימוש בממשק החומרה לפורמט שצוין על ידי הלקוח. AudioRecord.getActiveRecordingConfiguration()
.- מחזירה את הגדרות ההקלטה הפעילות.
כדי לקבל תצוגה כללית של כל ההקלטות הפעילות במכשיר, אפשר להפעיל את הפקודה AudioManager.getActiveRecordingConfigurations()
.