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