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

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

في بعض الأحيان، قد يحاول تطبيقان أو أكثر "التقاط" الإدخال الصوتي نفسه. وقد يؤدون مهام مختلفة. على سبيل المثال، قد تكون بعض التطبيقات التي تتلقّى الصوت "تسجّل"، مثل مسجّل صوت بسيط، بينما قد تكون تطبيقات أخرى "تستمع"، مثل "مساعد Google" أو خدمة تسهيل الاستخدام التي تستجيب للطلبات الصوتية.

وفي كلتا الحالتين، تريد هذه التطبيقات تلقّي إدخال صوتي. في هذه الصفحة، نستخدم مصطلح "الالتقاط" بغض النظر عمّا إذا كان التطبيق يسجّل الصوت أو يستمع إليه فقط.

إذا أراد تطبيقان أو أكثر تسجيل الصوت في الوقت نفسه، قد تحدث مشكلة في توصيل الإشارة الصوتية من المصدر نفسه إلى جميع التطبيقات. توضّح هذه الصفحة كيفية مشاركة نظام Android لإدخال الصوت بين تطبيقات متعددة تسجّل الصوت.

سلوك ما قبل الإصدار 10 من نظام التشغيل Android

قبل الإصدار Android 10، كان بإمكان تطبيق واحد فقط في كل مرة تسجيل البث الصوتي المُدخل. إذا كان هناك تطبيق آخر يسجّل الصوت أو يستمع إليه، يمكن لتطبيقك إنشاء عنصر AudioRecord، ولكن سيظهر خطأ عند استدعاء AudioRecord.startRecording() ولن يبدأ التسجيل.

كان أحد الاستثناءات لهذه القاعدة هو عندما يحصل تطبيق ذو امتيازات (مثل "مساعد Google" أو خدمة تسهيل الاستخدام) على إذن android.permission.CAPTURE_AUDIO_HOTWORD ويستخدم مصدرًا صوتيًا من النوع HOTWORD. في هذه الحالة، يمكن لتطبيق آخر بدء التسجيل. عندما حدث ذلك، تم إنهاء التطبيق المتميز والتقط التطبيق الجديد الإدخال.

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

سلوك Android 10

أما في الإصدارات السابقة من Android 10، فيتم منح الأولوية للتطبيق الذي يطلب الوصول أولاً. عندما يبدأ تطبيق في تسجيل الصوت، لا يمكن لأي تطبيقات أخرى الوصول إلى مصدر إدخال الصوت إلى أن يتوقف التطبيق الذي يسجّل الصوت.

يفرض نظام التشغيل Android 10 نظامًا للأولوية يمكنه تبديل البث الصوتي للإدخال بين التطبيقات أثناء تشغيلها. في معظم الحالات، إذا حصل تطبيق جديد على إذن الوصول إلى مصدر الصوت، سيستمر تشغيل التطبيق الذي كان يسجّل الصوت سابقًا، ولكنّه سيسجّل صمتًا. في بعض الحالات، يمكن أن يستمر النظام في إرسال الصوت إلى كلا التطبيقين. في ما يلي شرح لسيناريوهات المشاركة المختلفة.

يشبه هذا المخطط الطريقة التي يتعامل بها التركيز الصوتي مع تطبيقات متعددة تتنافس على استخدام مخرجات الصوت. ومع ذلك، تتم إدارة التركيز على الصوت من خلال طلبات برمجية للحصول على التركيز وإلغائه، بينما يعتمد نظام تبديل الإدخال الموضّح هنا على سياسة تحديد الأولويات التي يتم تطبيقها تلقائيًا عندما يبدأ تطبيق جديد في تسجيل الصوت.

لغرض تسجيل الصوت، يميّز Android بين نوعَين من التطبيقات:

  • يتم تثبيت التطبيقات "العادية" من قِبل المستخدم.
  • تكون التطبيقات "المميّزة" مثبَّتة مسبقًا على الجهاز. وتشمل هذه الخدمات "مساعد Google" وجميع خدمات تسهيل الاستخدام.

بالإضافة إلى ذلك، تتم معاملة التطبيق بشكل مختلف إذا كان يستخدم مصدر صوت "حساسًا للخصوصية": CAMCORDER أو VOICE_COMMUNICATION.

في ما يلي قواعد تحديد الأولوية لاستخدام الإدخال الصوتي ومشاركته:

  • وتكون للتطبيقات المميّزة أولوية أعلى من التطبيقات العادية.
  • تحظى التطبيقات التي تتضمّن واجهات مستخدم مرئية في المقدّمة بأولوية أعلى من التطبيقات التي تعمل في الخلفية.
  • تحظى التطبيقات التي تسجّل الصوت من مصدر حسّاس للخصوصية بأولوية أعلى من التطبيقات التي لا تفعل ذلك.
  • لا يمكن لتطبيقَين عاديَين تسجيل الصوت في الوقت نفسه.
  • في بعض الحالات، يمكن لتطبيق ذي امتيازات مشاركة الإدخال الصوتي مع تطبيق آخر.
  • إذا كان هناك تطبيقان في الخلفية لهما الأولوية نفسها يسجّلان الصوت، تكون الأولوية الأعلى للتطبيق الذي بدأ التسجيل مؤخرًا.

سيناريوهات المشاركة

عندما يحاول تطبيقان تسجيل الصوت، قد يتمكّن كلاهما من تلقّي إشارة الإدخال، أو قد يتلقّى أحدهما صوتًا صامتًا.

هناك أربعة سيناريوهات رئيسية:

  • ‫"مساعد Google" + تطبيق عادي
  • خدمة مخصّصة لتسهيل الاستخدام + تطبيق عادي
  • تطبيقان عاديان
  • مكالمة صوتية + تطبيق عادي

‫Assistant + تطبيق عادي

يُعدّ "مساعد Google" تطبيقًا مميزًا لأنّه مثبَّت مسبقًا ويحمل الدور RoleManager.ROLE_ASSISTANT. ويتم التعامل مع أي تطبيق آخر مثبّت مسبقًا بهذا الدور بشكل مشابه.

يشارك Android الصوت المُدخَل وفقًا للقواعد التالية:

  • يمكن لـ "مساعد Google" تلقّي الصوت (سواء كان في المقدّمة أو في الخلفية) ما لم يكن هناك تطبيق آخر يستخدم مصدر صوت حسّاسًا للخصوصية ويسجّل الصوت حاليًا.

  • يتلقّى التطبيق الصوت ما لم يتضمّن "مساعد Google" عنصر واجهة مستخدم مرئيًا في أعلى الشاشة.

يُرجى العِلم أنّ كلا التطبيقَين يتلقّيان الصوت فقط عندما يكون "مساعد Google" في الخلفية ولا يسجّل التطبيق الآخر الصوت من مصدر صوتي حسّاس للخصوصية.

خدمة مخصّصة لتسهيل الاستخدام + تطبيق عادي

يتطلّب AccessibilityService بيانًا صارمًا.

يشارك Android الصوت المُدخَل وفقًا للقواعد التالية:

  • إذا كانت واجهة مستخدم الخدمة في المقدّمة، يتلقّى كل من الخدمة والتطبيق الإدخال الصوتي. يوفّر هذا السلوك وظائف مثل التحكّم في مكالمة صوتية أو تسجيل فيديو باستخدام الطلبات الصوتية.

  • إذا لم تكن الخدمة في المقدّمة، يتم التعامل مع هذه الحالة مثل حالة التطبيقَين العادية أدناه.

تطبيقان عاديان

عندما يسجّل تطبيقان الصوت في الوقت نفسه، يتلقّى تطبيق واحد فقط الصوت، بينما يتلقّى التطبيق الآخر صوتًا صامتًا.

يشارك Android الصوت المُدخَل وفقًا للقواعد التالية:

  • إذا لم يكن أيّ من التطبيقَين حسّاسًا للخصوصية، يتلقّى التطبيق الذي يتضمّن واجهة مستخدم في الأعلى الصوت. إذا لم يكن لأي من التطبيقَين واجهة مستخدم، يتلقّى التطبيق الذي بدأ التسجيل مؤخرًا الصوت.
  • إذا كان أحد التطبيقَين حساسًا للخصوصية، سيتلقّى الصوت، بينما يتلقّى التطبيق الآخر صمتًا حتى إذا كانت لديه واجهة مستخدم في الأعلى أو بدأ التسجيل مؤخرًا.
  • إذا كان كلا التطبيقين حسّاسين للخصوصية، يتلقّى التطبيق الذي بدأ التسجيل مؤخرًا الصوت، بينما يتلقّى التطبيق الآخر صمتًا.

مكالمة صوتية + تطبيق عادي

تكون المكالمة الصوتية نشطة إذا كان وضع الصوت الذي يعرضه AudioManager.getMode() هو MODE_IN_CALL أو MODE_IN_COMMUNICATION.

يشارك Android الصوت المُدخَل وفقًا للقواعد التالية:

سلوك Android 11

يتبع نظام التشغيل Android 11 (المستوى 30 لواجهة برمجة التطبيقات) مخطّط الأولوية في Android 10 الموضّح أعلاه. وتوفّر أيضًا طرقًا جديدة في 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().