جارٍ مشاركة إدخال الصوت

يأتي إدخال الصوت عادةً من الميكروفون المدمج أو ميكروفون خارجي أو واجهة صوتية متصلة بالجهاز. يمكن أن يأتي الإدخال الصوتي أيضًا من محادثة هاتفية.

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

سلوك Android 11

يتبع الإصدار 11 من نظام التشغيل Android (المستوى 30 لواجهة برمجة التطبيقات) نظام الأولوية في الإصدار 10 من نظام التشغيل Android الموضّح أعلاه. وتوفّر أيضًا طرقًا جديدة في AudioRecord وMediaRecorder وAAudioStream تتيح تفعيل وإيقاف إمكانية تسجيل الصوت بشكل متزامن، بغض النظر عن حالة الاستخدام المحدّدة.

الطرق الجديدة هي:

عندما تكون قيمة setPrivacySensitive() هي true، تكون حالة استخدام الالتقاط خاصة ولا يمكن حتى لمستخدم "مساعد Google" لديه امتيازات التقاط المحتوى بشكل متزامن. يلغي هذا الإعداد السلوك التلقائي الذي يعتمد على مصدر الصوت. على سبيل المثال، تكون VOICE_COMMUNICATION خاصة بشكل تلقائي، ولكن UNPROCESSED ليست كذلك.

التغييرات في الإعدادات

عندما تسجّل عدة تطبيقات الصوت في الوقت نفسه، يكون تطبيق واحد أو تطبيقان فقط "نشطَين" (يتلقّيان الصوت)، بينما تكون التطبيقات الأخرى مكتومة (تتلقّى صمتًا). عندما تتغير التطبيقات النشطة، قد يعيد إطار عمل الصوت ضبط مسارات الصوت وفقًا للقواعد التالية:

  • قد يتغيّر جهاز إدخال الصوت لكل تطبيق نشط (على سبيل المثال، من الميكروفون المدمج إلى سمّاعة رأس متصلة عبر البلوتوث).
  • يتم تفعيل المعالجة المُسبقة المرتبطة بالتطبيق النشط ذي الأولوية الأعلى. ويتم تجاهل جميع عمليات المعالجة المسبقة الأخرى.

بما أنّ التطبيق النشط قد يتم إسكاته عندما يصبح تطبيق ذو أولوية أعلى نشطًا، يمكنك تسجيل AudioManager.AudioRecordingCallback في العنصر AudioRecord أو MediaRecorder ليتم إعلامك عند تغيير الإعدادات. يمكن أن تشمل التغييرات المحتملة ما يلي:

  • تسجيل الصوت مكتومًا أو غير مكتوم
  • تم تغيير الجهاز
  • تم تغيير المعالجة المُسبقة
  • تم تغيير خصائص البث (معدّل البيانات في الملف الصوتي، وقناع القناة، وتنسيق البيانات في الملف الصوتي)

يجب الاتصال بالرقم AudioRecord.registerAudioRecordingCallback() قبل بدء عملية الالتقاط. لا يتم تنفيذ دالة الرجوع إلا عندما يتلقّى التطبيق صوتًا ويحدث تغيير.

تعرض الطريقة onRecordingConfigChanged() AudioRecordingConfiguration يحتوي على حالة تسجيل الصوت الحالية. يمكنك استخدام الطرق التالية للتعرّف على التغيير:

isClientSilenced()
تعرض هذه السمة القيمة "صحيح" إذا كان الصوت الذي تم إرجاعه إلى العميل يتم كتمه حاليًا بسبب سياسة التسجيل.
getAudioDevice()
تعرض هذه السمة جهاز الصوت النشط.
getEffects()
تعرض هذه السمة تأثير المعالجة المُسبقة النشط. يُرجى العِلم أنّ التأثير النشط قد لا يكون هو نفسه التأثيرات التي تعرضها الدالة getClientEffects() إذا لم يكن التطبيق هو التطبيق النشط ذو الأولوية الأعلى.
getFormat()
تعرِض هذه السمة خصائص البث. يُرجى العِلم أنّ بيانات الصوت الفعلية التي يتلقّاها العميل تتوافق دائمًا مع التنسيق المطلوب الذي تعرضه getClientFormat(). يُجري إطار العمل تلقائيًا إعادة أخذ العيّنات والقنوات وتحويل التنسيق اللازمة من التنسيق المستخدَم في واجهة الأجهزة إلى التنسيق الذي يحدّده العميل.
AudioRecord.getActiveRecordingConfiguration().
تعرض هذه السمة إعدادات التسجيل النشطة.

يمكنك الحصول على نظرة عامة على جميع التسجيلات النشطة على الجهاز من خلال الاتصال بالرقم AudioManager.getActiveRecordingConfigurations().