تأتي عادةً إشارة إدخال الصوت من الميكروفون المدمج أو ميكروفون خارجي أو واجهة صوتية متصلة بالجهاز. يمكن أيضًا أن تأتي الإدخالات الصوتية من محادثة هاتفية.
قد يحتاج تطبيقان أو أكثر أحيانًا إلى "تسجيل" الإدخال الصوتي نفسه. قد يكونون يؤدون مهام مختلفة. على سبيل المثال، قد تكون بعض التطبيقات التي تتلقّى الصوت "مسجّلة"، مثل مسجل صوتي بسيط، في حين قد تكون تطبيقات أخرى "مستمعًا"، مثل "مساعد Google" أو خدمة تسهيل الاستخدام التي تستجيب للأوامر الصوتية.
وفي كلتا الحالتَين، تريد هذه التطبيقات تلقّي إدخال صوتي. في هذه الصفحة، نستخدم مصطلح "التسجيل" بغض النظر عمّا إذا كان أحد التطبيقات يُسجّل الصوت أو يستمع إليه فقط.
إذا أراد تطبيقان أو أكثر تسجيل الصوت في الوقت نفسه، قد تحدث مشكلة في إرسال إشارة الصوت من المصدر نفسه إلى جميع التطبيقات. توضِّح هذه الصفحة كيفية مشاركة نظام Android للبيانات الصوتية الواردة بين تطبيقات متعددة تسجِّل الصوت.
السلوك في الإصدارات الأقدم من Android 10
قبل الإصدار 10 من Android، كان بإمكان تطبيق واحد فقط تسجيل بث الصوت المُدخل في كل مرة. إذا كان أحد التطبيقات يسجّل الصوت أو يستمع إليه، يمكن لتطبيقك
إنشاء عنصر AudioRecord
، ولكن ستظهر رسالة خطأ عند استدعاء
AudioRecord.startRecording()
ولن يبدأ التسجيل.
كان هناك استثناء واحد لهذه القاعدة، وهو عندما يكون لدى تطبيق مميّز (مثل "مساعد Google" أو
خدمة تسهيل الاستخدام) الإذن
android.permission.CAPTURE_AUDIO_HOTWORD
وكان يستخدم مصدر صوت من النوع
HOTWORD
. في هذه الحالة، يمكن أن يبدأ تطبيق آخر التسجيل. عند حدوث ذلك، تم إنهاء
التطبيق المزوّد بامتيازات وتلقّى التطبيق الجديد الإدخال.
تم إجراء تغيير آخر في Android 9: يمكن للتطبيقات التي تعمل في المقدّمة فقط (أو الخدمة التي تعمل في المقدّمة) تسجيل الإدخال الصوتي. عندما يبدأ تطبيق بدون خدمة تعمل في المقدّمة أو مكوّن واجهة مستخدم يعمل في المقدّمة في التسجيل، يواصل التطبيق التشغيل ولكنّه يتلقّى صوتًا صامتًا، حتى لو كان التطبيق الوحيد الذي يسجّل الصوت في ذلك الوقت.
سلوك Android 10
كان السلوك في الإصدارات الأقدم من Android 10 هو "المستخدمون الأوائل هم من يحصلون على المساحة أولاً". بعد أن يبدأ أحد التطبيقات في تسجيل الصوت، لا يمكن لأي تطبيقات أخرى الوصول إلى إدخال الصوت إلى أن يتوقف التطبيق عن تسجيل الصوت.
يفرض نظام التشغيل Android 10 مخطط أولوية يمكنه تبديل بث الصوت المُدخل بين التطبيقات أثناء تشغيلها. في معظم الحالات، إذا حصل تطبيق جديد على الإدخال الصوتي، يستمر تشغيل التطبيق الذي كان يُسجّل الصوت سابقًا، ولكنّه يتلقّى صمتًا. في بعض الحالات، يمكن للنظام مواصلة إرسال الصوت إلى كلا التطبيقَين. في ما يلي شرح لسيناريوهات المشاركة المختلفة.
يشبه هذا المخطط الطريقة التي يتعامل بها "تركيز الصوت" مع التطبيقات المتعدّدة التي تتصارع على استخدام إخراج الصوت. ومع ذلك، يتم إدارة تركيز الصوت من خلال الطلبات الآلية للحصول على التركيز وإزالته، في حين يستند أسلوب التبديل بين مصادر الإدخال описан هنا إلى سياسة تحديد الأولويات التي يتم تطبيقها تلقائيًا عندما يبدأ تطبيق جديد في تسجيل الصوت.
لأغراض تسجيل الصوت، يميز Android بين نوعَين من التطبيقات:
- يُثبِّت المستخدم التطبيقات "العادية".
- تكون التطبيقات "المفوَّضة" مثبَّتة مسبقًا على الجهاز. وتشمل هذه الخدمات "مساعد Google" وجميع خدمات تسهيل الاستخدام.
بالإضافة إلى ذلك، يتم التعامل مع التطبيق بشكل مختلف
إذا كان يستخدم مصدرًا صوتيًا "حساسًا للخصوصية":
CAMCORDER
أو VOICE_COMMUNICATION
.
في ما يلي قواعد تحديد الأولوية لاستخدام الإدخال الصوتي ومشاركته:
- تكون التطبيقات المميّزة ذات أولوية أعلى من التطبيقات العادية.
- تكون التطبيقات التي تعرض واجهة مستخدم مرئية في المقدّمة ذات أولوية أعلى من التطبيقات التي تعمل في الخلفية.
- تكون التطبيقات التي تلتقط الصوت من مصدر حسّاس للخصوصية لها الأولوية على التطبيقات التي لا تفعل ذلك.
- لا يمكن لأي تطبيقَين عاديين تسجيل الصوت في الوقت نفسه.
- في بعض الحالات، يمكن لتطبيق مفوَّض مشاركة الإدخال الصوتي مع تطبيق آخر.
- إذا كان هناك تطبيقان في الخلفية لهما الأولوية نفسها يسجّلان الصوت، يكون للتطبيق الذي تم تشغيله مؤخرًا أولوية أعلى.
مشاركة السيناريوهات
عندما يحاول تطبيقان تسجيل الصوت، قد يتمكّن كلاهما من تلقّي إشارة الإدخال، أو قد يتلقّى أحدهما صوتًا صامتًا.
هناك أربعة سيناريوهات رئيسية:
- "مساعد Google" + تطبيق عادي
- خدمة أدوات تسهيل الاستخدام + تطبيق عادي
- تطبيقان عاديان
- مكالمة صوتية + تطبيق عادي
"مساعد Google" + تطبيق عادي
"مساعد Google" هو تطبيق مفوَّض لأنّه مثبَّت مسبقًا ويحمل دور RoleManager.ROLE_ASSISTANT
.
ويتم التعامل بالطريقة نفسها مع أي تطبيق آخر مثبَّت مسبقًا لديه هذا الدور.
يشارك Android المحتوى الصوتي الذي يتم إدخاله وفقًا للقواعد التالية:
يمكن أن يتلقّى "مساعد Google" الصوت (سواء كان في المقدّمة أو الخلفية) ما لم يكن هناك تطبيق آخر يستخدم مصدر صوت حسّاسًا للخصوصية.
يتلقّى التطبيق الصوت ما لم يكن لدى "مساعد Google" عنصر واجهة مستخدم مرئي في أعلى الشاشة.
يُرجى العِلم أنّ كلا التطبيقَين لا يتلقّيان الصوت إلا عندما يكون "مساعد Google" في الخلفية ولا يُسجِّل التطبيق الآخر الصوت من مصدر صوت حسّاس للخصوصية.
خدمة أدوات تسهيل الاستخدام + تطبيق عادي
يتطلّب 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
يتّبع الإصدار 11 من نظام التشغيل Android (المستوى 30 لواجهة برمجة التطبيقات) مخطّط الأولوية في الإصدار 10 من Android описан أعلاه. وتوفّر أيضًا طرقًا جديدة في AudioRecord
وMediaRecorder
و
AAudioStream
لتفعيل إمكانية تسجيل الصوت في الوقت نفسه وإيقافها،
بغض النظر عن حالة الاستخدام المحدّدة.
في ما يلي الطرق الجديدة:
AudioRecord.Builder.setPrivacySensitive()
AudioRecord.isPrivacySensitive()
MediaRecorder.setPrivacySensitive()
MediaRecorder.isPrivacySensitive()
AAudioStreamBuilder_setPrivacySensitive()
AAudioStream_isPrivacySensitive()
عندما يكون setPrivacySensitive()
هو true
، تكون حالة استخدام الالتقاط خاصة ولا يمكن حتى
لـ "مساعد Google" المفوَّض التقاط البيانات بشكل متزامن. يلغي هذا الإعداد السلوك
التلقائي الذي يعتمد على مصدر الصوت. على سبيل المثال،
VOICE_COMMUNICATION
خاصة تلقائيًا ولكن UNPROCESSED
ليست كذلك.
تغييرات الإعدادات
عندما تلتقط عدة تطبيقات الصوت في الوقت نفسه، يكون تطبيق واحد أو تطبيقان فقط "نشطَين" (يتلقّيان الصوت)، ويتم كتم صوت التطبيقات الأخرى (لا يتلقّى أي صوت). عند تغيير التطبيقات النشطة، قد يعيد إطار العمل الصوتي ضبط مسارات الصوت وفقًا للقواعد التالية:
- قد يتغيّر جهاز إرسال الصوت لكل تطبيق نشط (على سبيل المثال، من الميكروفون المدمج إلى سماعة رأس بلوتوث متصلة).
- يتم تفعيل المعالجة المُسبَقة المرتبطة بالتطبيق النشط الأعلى أولوية. ويتم تجاهل كل المعالجة المسبقة الأخرى.
بما أنّه قد يتم كتم صوت تطبيق نشط عندما يصبح تطبيق ذو أولوية أعلى نشطًا،
يمكنك تسجيل AudioManager.AudioRecordingCallback
في AudioRecord
أو MediaRecorder
لتلقّي إشعار عند تغيير الإعدادات.
يمكن أن تكون التغييرات المحتملة على النحو التالي:
- تسجيل الصوت مكتومًا أو غير مكتوم
- تم تغيير الجهاز
- تم تغيير المعالجة المُسبَقة
- تغيّرت خصائص مصدر البيانات (معدّل أخذ العينات وقناع القناة وتنسيق العيّنة)
يجب الاتصال برقم AudioRecord.registerAudioRecordingCallback()
قبل بدء عملية الالتقاط.
لا يتم تنفيذ طلب إعادة الاتصال إلا عندما يتلقّى التطبيق الصوت ويحدث تغيير.
تُرجع الطريقة onRecordingConfigChanged()
AudioRecordingConfiguration
يحتوي على حالة تسجيل الصوت الحالية. يمكنك استخدام الخطوات التالية لتلقّي معلومات عن التغيير:
isClientSilenced()
- يعرض القيمة "صحيح" إذا كان يتم كتم صوت المقطع الصوتي الذي يتم إرجاعه إلى العميل حاليًا بسبب سياسة التسجيل.
getAudioDevice()
- يعرض الجهاز الصوتي النشط.
getEffects()
- يعرض تأثير المعالجة المُسبَقة النشط. يُرجى العِلم أنّ التأثير النشط قد لا يكون مطابقًا للتأثيرات التي تعرضها
getClientEffects()
إذا لم يكن العميل هو التطبيق النشط الأعلى أولوية. getFormat()
- تعرض خصائص مصدر البيانات. يُرجى العِلم أنّ بيانات الصوت الفعلية التي يتلقّاها العميل تلتزم دائمًا بالتنسيق المطلوب الذي يعرضه
getClientFormat()
. يُجري إطار العمل تلقائيًا عمليات إعادة أخذ العينات والتحويل اللازمة للقنوات والتنسيقات من التنسيق المستخدَم في واجهة الجهاز إلى التنسيق الذي يحدّده العميل. AudioRecord.getActiveRecordingConfiguration()
.- يعرض إعدادات التسجيل النشطة.
يمكنك الحصول على نظرة عامة على جميع التسجيلات النشطة على الجهاز من خلال الاتصال بالرقم
AudioManager.getActiveRecordingConfigurations()
.