קלט האודיו מגיע בדרך כלל מהמיקרופון המובנה, ממיקרופון חיצוני או מממשק אודיו שמחובר למכשיר. קלט אודיו יכול להגיע גם משיחה בטלפון.
לפעמים שתי אפליקציות או יותר רוצות 'לתפוס' את אותו קלט אודיו. יכול להיות שהם מבצעים משימות שונות. לדוגמה, יכול להיות שאפליקציות מסוימות שמקבלות אודיו יבצעו 'הקלטה', כמו אפליקציית הקלטה פשוטה, ואפליקציות אחרות יבצעו 'האזנה', כמו 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.כדי להקליט את הערוץ העולה (TX), הערוץ היורד (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()
- Returns the active preprocessing effect. שימו לב: יכול להיות שהאפקט הפעיל לא יהיה זהה לאפקטים שמוחזרים על ידי
getClientEffects()אם הלקוח הוא לא האפליקציה הפעילה עם העדיפות הכי גבוהה. getFormat()- מחזירה את מאפייני הזרם. שימו לב שנתוני האודיו בפועל שמתקבלים על ידי הלקוח תמיד תואמים לפורמט הנדרש שמוחזר על ידי
getClientFormat(). המסגרת מבצעת באופן אוטומטי את הדגימה מחדש, ההמרה של הערוץ וההמרה של הפורמט מהפורמט שבו נעשה שימוש בממשק החומרה לפורמט שצוין על ידי הלקוח. AudioRecord.getActiveRecordingConfiguration().- מחזירה את הגדרות התיעוד הפעילות.
כדי לקבל תצוגה כללית של כל ההקלטות הפעילות במכשיר, אפשר להשתמש בפקודה
AudioManager.getActiveRecordingConfigurations().