تقویت صدای پس‌زمینه

از اندروید ۱۷ به بعد، چارچوب صوتی محدودیت‌هایی را بر تعاملات صوتی پس‌زمینه از جمله پخش صدا، درخواست‌های فوکوس صدا و APIهای تغییر صدا اعمال می‌کند تا اطمینان حاصل شود که این تغییرات عمداً توسط کاربر آغاز می‌شوند.

اگر یک توسعه‌دهنده برنامه قصد دارد صدا را بدون یک فعالیت قابل مشاهده کنترل کند، باید مطمئن شود که برنامه دارای یک سرویس پیش‌زمینه (که از نوع SHORT_SERVICE نباشد) است که با قابلیت‌های در حال استفاده (WIU) راه‌اندازی شده است. یک سرویس پیش‌زمینه در صورتی قابلیت‌های WIU را دریافت می‌کند که در پاسخ به یک MediaSessionEvent یا در حالی که برنامه برای کاربر قابل مشاهده است، راه‌اندازی شود.

اگر برنامه سعی کند APIهای صوتی را در حالی که برنامه در چرخه حیات معتبری نیست، فراخوانی کند، APIهای پخش صدا و تغییر صدا بدون ایجاد استثنا یا ارائه پیام خطا، بی‌صدا با شکست مواجه می‌شوند. API فوکوس صوتی با کد نتیجه AUDIOFOCUS_REQUEST_FAILED با شکست مواجه می‌شود.

هدف از اعمال این محدودیت‌ها، کاهش تجربه‌های ناخواسته‌ی مشکلات صوتی پس‌زمینه است. برخی از نمونه‌ها عبارتند از:

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

ما توسعه‌دهندگان را تشویق می‌کنیم که برنامه‌های خود را آزمایش کنند و در صورت وجود هرگونه مورد استفاده عمدی از صدا که تأثیر منفی داشته باشد، بازخورد خود را در مورد تغییر رفتار ارائه دهند. لطفاً هرگونه مشکلی را با استفاده از این ردیاب مشکلات سازگاری برنامه اندروید ۱۷ گزارش دهید.

موارد استفاده از صدای پس‌زمینه تحت تأثیر را شناسایی کنید

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

اگر برنامه شما فقط قصد پخش صدا یا استفاده از APIهای صوتی را در حین نمایش یک فعالیت قابل مشاهده برای کاربر، از جمله استفاده از حالت تصویر در تصویر (PiP) دارد، تحت تأثیر هیچ یک از این تغییرات قرار نمی‌گیرد.

اگر برنامه شما قابلیت VOIP، از جمله برنامه‌های تماس ویدیویی را ارائه می‌دهد، باید از قبل الزامات معرفی شده برای پخش (معمولاً از طریق استفاده از APIهای مخابراتی توصیه شده) را برای ضبط موفقیت‌آمیز صدا برآورده کند و بنابراین بعید است که تحت تأثیر قرار گیرد.

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

سناریوهای صوتی پس‌زمینه که احتمالاً تأثیر خواهند گذاشت

اگر برنامه شما از مدل ادامه تعامل صوتی که هنگام باز بودن برنامه یا در پاسخ به یک اقدام صریح کاربر آغاز شده است، پیروی نکند، احتمالاً عملکرد برنامه شما به طور خاموش سرکوب خواهد شد.

برای مثال، اگر برنامه شما در پاسخ به BOOT_COMPLETE یک سرویس پیش‌زمینه را اجرا کند و سعی در تعامل با صدا داشته باشد، این سرویس سرکوب خواهد شد.

بهترین شیوه‌های صوتی پس‌زمینه برای کاهش تأثیر

  • برای مدیریت پخش صدای پس‌زمینه، از کامپوننت MediaSessionService کتابخانه‌ی جت‌پک media3 استفاده کنید.

    اگر این کار را انجام دهید، به دلیل کمک کتابخانه در مدیریت چرخه عمر پخش، بعید است برنامه شما تحت تأثیر سخت شدن پس‌زمینه قرار گیرد.

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

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

    انجام این کار تضمین می‌کند که سرویس پیش‌زمینه با قابلیت‌های WIU آغاز می‌شود.

  • در طول خرابی‌های گذرای کمتر از ۱۰ دقیقه، mediaPlayback FGS را فعال نگه دارید.

    اگر برنامه شما دچار یک خطای گذرا شود، مانند مشکل بافرینگ به دلیل فعالیت شبکه، یا یک وقفه گذرای مورد انتظار مانند AUDIOFOCUS_LOSS_TRANSIENT ، قصد پخش باید ادامه یابد. بنابراین FGS شما باید فعال بماند.

  • سرویس پیش‌زمینه را در پایان پخش متوقف کنید و پخش را فقط در صورتی که کاربر صریحاً پخش را از سر بگیرد، مجدداً آغاز کنید.

    در صورت وجود سیگنال دائمی برای پایان پخش (برای مثال، محتوا بدون پخش خودکار، AUDIOFOCUS_LOSS ، رویداد مکث از UMO یا رویداد کلید رسانه) یا یک خرابی غیرقابل بازیابی، برنامه شما باید تعامل صوتی را متوقف کند، سرویس پیش‌زمینه را متوقف کند و جلسه رسانه را پایان دهد. انجام همه این کارها مطابق با تصور کاربر از "پایان دادن" به تعامل صوتی پس‌زمینه مورد نظر است. پس از انجام این کار، برنامه شما دیگر قابلیت‌های تعامل صوتی پس‌زمینه را ندارد.

    متعاقباً، اگر کاربر به طور صریح پخش را از سر بگیرد، مثلاً از طریق رابط کاربری برنامه شما یا از طریق دکمه پخش Universal Media Object، هدف شروع پخش صدا باید بازگردد و در نتیجه یک FGS تازه شروع شده ایجاد شود.

  • رفتار پخش صدا را با دستورات پوسته adb آزمایش کنید.

آزمایش تغییرات در اندروید ۱۶ و اندروید ۱۷

این ویژگی از اندروید ۱۶ به بعد در سطح «هشدار» پیاده‌سازی شده است. این بدان معناست که برنامه‌ها می‌توانند adb shell cmd audio set-enable-hardening برای آزمایش دستی اجرای سخت‌سازی صدای پس‌زمینه استفاده کنند.

برای فعال کردن اجرای قانون در دستگاه‌هایی که اندروید ۱۶ دارند، دستور زیر را اجرا کنید:

adb shell cmd audio set-enable-hardening 1

برای غیرفعال کردن اجرای قانون در دستگاه‌هایی که اندروید ۱۷ را اجرا می‌کنند، دستور زیر را اجرا کنید:

adb shell cmd audio set-enable-hardening 0

ما همچنین توصیه می‌کنیم از logcat یا دستور adb adb dumpsys audio برای شناسایی اینکه آیا برنامه به دلیل اجرای سخت‌سازی صدا با شکست‌های خاموش مواجه شده است یا خیر، استفاده کنید. در صورت بروز این مشکل، ورودی با پیشوند AudioHardening به همراه نام بسته شما در گزارش وجود خواهد داشت.

آشنایی با FGS با قابلیت استفاده در حین استفاده

به‌طورکلی، سرویس‌های پیش‌زمینه (FGS) باید زمانی که یک برنامه در پیش‌زمینه است، راه‌اندازی شوند تا عملیات آغاز شده توسط کاربر را گسترش دهند. در برخی موارد خاص ، برنامه‌ها مجاز به راه‌اندازی یک سرویس پیش‌زمینه در حالی که برنامه در پس‌زمینه است، هستند. با این حال، این سرویس‌های پیش‌زمینه معمولاً قابلیت‌های «در حال استفاده» (WIU) را دریافت نمی‌کنند.

WIU به عنوان یک دروازه امنیتی عمل می‌کند - مانع از آن می‌شود که FGS که در پس‌زمینه شروع شده است، در مواقعی که کاربر ممکن است از فعالیت برنامه آگاه نباشد، درگیر رفتارهای حساس خاصی شود. این مانع از دسترسی برنامه به داده‌های حساس مانند مکان، دوربین یا میکروفون می‌شود و از اندروید ۱۷ به بعد، APIهای صوتی را که معمولاً به یک زمینه رابط کاربری قابل مشاهده نیاز دارند، نیز مسدود می‌کند.

در اینجا یک مرجع مفید وجود دارد:

  • FGS استاندارد: سرویس‌هایی که در حین مشاهده برنامه یا با مجوز اجرای فعالیت پس‌زمینه شروع به کار می‌کنند، دسترسی WIU دریافت می‌کنند.
  • FGS شروع‌شده از پس‌زمینه (BFSL): اکثر آنها دسترسی WIU را اعطا نمی‌کنند. استثنائات اصلی که WIU را اعطا می‌کنند، تعاملاتی هستند که شامل قصد صریح کاربر می‌شوند، مانند کلیک‌های اعلان، تعاملات ویجت یا رویدادهای کلید رسانه از یک دستگاه خارجی.
  • سیستم FGS را راه‌اندازی کرد: FGSهایی که با استفاده از واگذاری سیستم-سرور (برای مثال، با استفاده از کتابخانه جت‌پک تلکام) راه‌اندازی شده‌اند، به WIU دسترسی دارند.

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

لیست کامل APIهای صوتی تحت تأثیر قرار گرفته

عملکرد صوتی

نتیجه

APIهای تحت تأثیر

پخش صوتی

پخش بی‌صدا شده است

بدون استثنا، بدون پیام خطا توسط هیچ API ارائه نمی‌شود

AudioTrack.write()

(NDK) AAudioStream_write

OpenSL ES برای اندروید

هر کتابخانه رسانه‌ای سمت کلاینت که پخش را مدیریت می‌کند، مانند media3، Exoplayer و Oboe، نیز می‌تواند تحت تأثیر قرار گیرد.

درخواست فوکوس صوتی

تابع AUDIOFOCUS_REQUEST_FAILED را برمی‌گرداند.

هیچ تاثیری بر پخش صدای برنامه‌های دیگر ندارد، فوکوس به دست نمی‌آید

AudioManager.requestAudioFocus()

رابط‌های برنامه‌نویسی (API) برای حالت صدا و زنگ

هیچ تاثیری بر حالت زنگ یا میزان صدا ندارد (فراخوانی متد به طور بی‌صدا نادیده گرفته می‌شود)

بدون استثنا، بدون پیام خطا توسط هیچ API ارائه نمی‌شود

AudioManager.setStreamVolume()

AudioManager.setStreamMute()

AudioManager.adjustStreamVolume()

AudioManager.adjustVolume()

AudioManager.adjustSuggestedStreamVolume()

AudioManager.setRingerMode()