يأتي إدخال الصوت عادةً من الميكروفون المدمج أو ميكروفون خارجي أو واجهة صوتية متصلة بالجهاز. يمكن أن يأتي الإدخال الصوتي أيضًا من محادثة هاتفية.
في بعض الأحيان، قد يرغب تطبيقان أو أكثر في "تسجيل" الإدخال الصوتي نفسه. قد يكونون يؤدون مهام مختلفة. على سبيل المثال، قد "تسجّل" بعض التطبيقات الصوت، مثل مسجّل الصوت البسيط، بينما قد "تستمع" تطبيقات أخرى، مثل "مساعد 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" تطبيقًا ذا امتيازات لأنّه مثبَّت مسبقًا ويحمل الدور 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().