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