درحال هم‌رسانی ورودی صوتی

ورودی صدا معمولاً از میکروفون داخلی، میکروفون خارجی، یا رابط صوتی متصل به دستگاه دریافت می‌شود. ورودی صوتی می‌تواند از مکالمه تلفنی نیز باشد.

گاهی اوقات ممکن است دو یا چند برنامه بخواهند ورودی صوتی یکسانی را «ضبط» کنند. ممکن است درحال انجام کارهای مختلفی باشند. برای مثال، برخی‌از برنامه‌هایی که صدا دریافت می‌کنند ممکن است «درحال ضبط» باشند، مثل ضبط‌کننده صدای ساده، درحالی‌که برنامه‌های دیگر ممکن است «درحال گوش دادن» باشند، مثل «دستیار Google» یا سرویس دسترس‌پذیری که به فرمان‌های صوتی پاسخ می‌دهد.

در هر دو حالت، این برنامه‌ها می‌خواهند ورودی صوتی دریافت کنند. در سراسر این صفحه، ما از اصطلاح «ضبط» استفاده می‌کنیم، صرف‌نظر از اینکه برنامه درحال ضبط کردن باشد یا فقط گوش دهد.

اگر دو یا چند برنامه بخواهند هم‌زمان صدا ضبط کنند، ممکن است مشکلی در ارسال سیگنال صوتی از یک منبع به همه آن‌ها وجود داشته باشد. این صفحه توضیح می‌دهد که سیستم Android چگونه ورودی صوتی را بین چند برنامه که صدا ضبط می‌کنند هم‌رسانی می‌کند.

رفتار قبل‌از Android 10

قبل‌از 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.

قوانین اولویت‌بندی برای استفاده و هم‌رسانی ورودی صوتی به‌شرح زیر است:

  • برنامه‌های ممتاز اولویت بالاتری نسبت‌به برنامه‌های معمولی دارند.
  • برنامه‌هایی که واسط کاربر پیش‌زمینه نمایان دارند اولویت بالاتری نسبت‌به برنامه‌های پس‌زمینه دارند.
  • برنامه‌هایی که صدا را از منبع حساس به حریم خصوصی ضبط می‌کنند اولویت بالاتری نسبت به برنامه‌هایی دارند که این کار را نمی‌کنند.
  • دو برنامه معمولی هرگز نمی‌توانند به‌طور هم‌زمان صدا ضبط کنند.
  • در برخی شرایط، برنامه دارای امتیاز می‌تواند ورودی صوتی را با برنامه دیگری هم‌رسانی کند.
  • اگر دو برنامه پس‌زمینه با اولویت یکسان درحال ضبط صدا باشند، برنامه‌ای که دیرتر شروع شده است اولویت بالاتری دارد.

هم‌رسانی سناریوها

وقتی دو برنامه سعی می‌کنند صدا ضبط کنند، ممکن است هر دو بتوانند سیگنال ورودی را دریافت کنند، یا ممکن است یکی از آن‌ها سکوت دریافت کند.

چهار سناریو اصلی وجود دارد:

  • دستیار + برنامه معمولی
  • سرویس دسترس‌پذیری + برنامه معمولی
  • دو برنامه معمولی
  • تماس گفتاری + برنامه معمولی

دستیار + برنامه معمولی

«دستیار» برنامه‌ای با دسترسی‌های ویژه است چون ازقبل نصب شده است و نقش RoleManager.ROLE_ASSISTANT را دارد. با هر برنامه ازپیش‌نصب‌شده دیگری که این نقش را داشته باشد به‌طور مشابه رفتار می‌شود.

Android صدای ورودی را طبق این قوانین هم‌رسانی می‌کند:

  • «دستیار» می‌تواند صدا دریافت کند (صرف‌نظر از اینکه در پیش‌زمینه باشد یا پس‌زمینه)، مگر اینکه برنامه دیگری که از منبع صوتی حساس به حریم خصوصی استفاده می‌کند درحال ضبط باشد.

  • برنامه صدا را دریافت می‌کند، مگراینکه «دستیار» عنصر رابط کاربری نمایانی در بالای صفحه داشته باشد.

توجه داشته باشید که هر دو برنامه فقط زمانی صدا دریافت می‌کنند که «دستیار» در پس‌زمینه باشد و برنامه دیگر از منبع صوتی حساس به حریم خصوصی ضبط نکند.

سرویس دسترس‌پذیری + برنامه معمولی

AccessibilityService به اظهارنامه دقیق نیاز دارد.

Android صدای ورودی را طبق این قوانین هم‌رسانی می‌کند:

  • اگر واسط کاربر سرویس در بالا باشد، هم سرویس و هم برنامه ورودی صوتی را دریافت می‌کنند. این رفتار عملکردهایی مانند کنترل تماس صوتی یا ضبط ویدیو با فرمان‌های صوتی را ارائه می‌دهد.

  • اگر سرویس در بالا نباشد، این مورد مانند مورد معمولی دو برنامه در زیر تلقی می‌شود.

دو برنامه معمولی

وقتی دو برنامه به‌طور هم‌زمان درحال ضبط هستند، فقط یکی از برنامه‌ها صدا را دریافت می‌کند و برنامه دیگر سکوت دریافت می‌کند.

Android صدای ورودی را طبق این قوانین هم‌رسانی می‌کند:

  • اگر هیچ‌کدام از برنامه‌ها نسبت‌به حریم خصوصی حساس نباشند، برنامه‌ای که واسط کاربر آن در بالا قرار دارد صدا را دریافت می‌کند. اگر هیچ‌کدام از برنامه‌ها واسط کاربر نداشته باشند، برنامه‌ای که اخیراً ضبط را شروع کرده است صدا را دریافت می‌کند.
  • اگر یکی از برنامه‌ها نسبت‌به حریم خصوصی حساس باشد، صدا را دریافت می‌کند و برنامه دیگر سکوت دریافت می‌کند، حتی اگر واسط کاربری آن در بالا باشد یا ضبط را اخیراً شروع کرده باشد.
  • اگر هر دو برنامه ازنظر حریم خصوصی حساس باشند، برنامه‌ای که اخیراً ضبط را شروع کرده است صدا را دریافت می‌کند و برنامه دیگر بی‌صدا می‌شود.

تماس گفتاری + برنامه معمولی

اگر حالت صوتی برگردانده‌شده توسط AudioManager.getMode()، MODE_IN_CALL یا MODE_IN_COMMUNICATION باشد، تماس گفتاری فعال است.

Android صدای ورودی را طبق این قوانین هم‌رسانی می‌کند:

رفتار Android 11

Android 11 (سطح میانای برنامه‌سازی کاربردی ۳۰) از طرح اولویت Android 10 که در بالا شرح داده شد پیروی می‌کند. همچنین روش‌های جدیدی در AudioRecord، MediaRecorder، و AAudioStream ارائه می‌دهد که امکان ضبط هم‌زمان صدا را بدون درنظر گرفتن مورد استفاده انتخاب‌شده فعال و غیرفعال می‌کند.

روش‌های جدید عبارت‌اند از:

وقتی setPrivacySensitive() true است، مورد استفاده ضبط خصوصی است و حتی «دستیار» ممتاز نمی‌تواند به‌طور هم‌زمان ضبط کند. این تنظیم رفتار پیش‌فرض را که به منبع صوتی بستگی دارد لغو می‌کند. برای مثال، VOICE_COMMUNICATION به‌طور پیش‌فرض خصوصی است اما UNPROCESSED این‌طور نیست.

تغییرات پیکربندی

وقتی چند برنامه به‌طور هم‌زمان درحال ضبط صدا هستند، فقط یک یا دو برنامه «فعال» هستند (صدا دریافت می‌کنند)؛ بقیه بی‌صدا هستند (سکوت دریافت می‌کنند). وقتی برنامه‌های فعال تغییر می‌کنند، چارچوب صوتی ممکن است مسیرهای صوتی را طبق این قوانین دوباره پیکربندی کند:

  • دستگاه ورودی صدا برای هر برنامه فعال ممکن است تغییر کند (برای مثال، از میکروفون داخلی به هدست بلوتوث متصل‌شده).
  • پیش‌پردازش مرتبط با فعال‌ترین برنامه با بالاترین اولویت فعال است. همه پیش‌پردازش‌های دیگر نادیده گرفته می‌شود.

ازآنجایی‌که ممکن است برنامه فعالی هنگام فعال شدن برنامه با اولویت بالاتر بی‌صدا شود، می‌توانید AudioManager.AudioRecordingCallback را در شیء AudioRecord یا MediaRecorder ثبت کنید تا هنگام تغییر پیکربندی مطلع شوید. تغییرات احتمالی می‌تواند شامل موارد زیر باشد:

  • ضبط بی‌صدا یا باصدا
  • دستگاه تغییر کرد
  • پیش‌پردازش تغییر کرد
  • ویژگی‌های جاری‌سازی تغییر کرد (نرخ نمونه‌برداری، ماسک کانال، قالب نمونه)

باید AudioRecord.registerAudioRecordingCallback() را قبل‌از شروع ضبط فراخوانی کنید. فراخوانی برگشتی فقط زمانی اجرا می‌شود که برنامه درحال دریافت صدا باشد و تغییری رخ دهد.

روش onRecordingConfigChanged() یک AudioRecordingConfiguration برمی‌گرداند که حاوی وضعیت ضبط صدای فعلی است. برای اطلاع از این تغییر، از روش‌های زیر استفاده کنید:

isClientSilenced()
اگر صدای برگردانده‌شده به کارخواه درحال‌حاضر به‌دلیل خط‌مشی ضبط بی‌صدا شده باشد، «درست» برمی‌گرداند.
getAudioDevice()
دستگاه صوتی فعال را برمی‌گرداند.
getEffects()
جلوه پیش‌پردازش فعال را برمی‌گرداند. توجه داشته باشید که اگر کارخواه فعال‌ترین برنامه با بالاترین اولویت نباشد، ممکن است جلوه فعال با جلوه‌هایی که getClientEffects() برمی‌گرداند یکسان نباشد.
getFormat()
ویژگی‌های جاری‌سازی را برمی‌گرداند. توجه داشته باشید که داده‌های صوتی واقعی دریافتی توسط کارخواه همیشه از قالب الزامی برگردانده‌شده توسط getClientFormat() پیروی می‌کند. چارچوب به‌طور خودکار نمونه‌برداری مجدد، کانال، و تبدیل قالب لازم را از قالب مورداستفاده در میانای سخت‌افزار به قالب مشخص‌شده توسط کارخواه انجام می‌دهد.
AudioRecord.getActiveRecordingConfiguration()
پیکربندی ضبط فعال را برمی‌گرداند.

با فراخوانی AudioManager.getActiveRecordingConfigurations() می‌توانید نمای کلی همه ضبط‌های فعال در دستگاه را دریافت کنید.