پشتیبانی از آرایش‌های سیستم

به‌روزرسانی‌های انجام‌شده در این مناطق ویژه نمایش در این صفحه ارائه می‌شود.

آرایش سیستم

‫Android 10 از پیکربندی نمایشگرهای ثانویه برای نمایش برخی‌از تزئینات سیستم، مثل کاغذدیواری، نوار پیمایش، و راه‌انداز پشتیبانی می‌کند. به‌طور پیش‌فرض، نمایشگر اصلی همه تزئینات سیستم را نشان می‌دهد و نمایشگرهای ثانویه تزئیناتی را نشان می‌دهند که به‌طور اختیاری فعال شده‌اند. می‌توانید پشتیبانی از ویرایشگر روش ورودی (IME) را جدا از سایر تزئینات سیستم تنظیم کنید.

از DisplayWindowSettings#setShouldShowSystemDecorsLocked برای افزودن پشتیبانی از تزئینات سیستم در نمایشگر خاصی استفاده کنید یا مقدار پیش‌فرضی در /data/system/display_settings.xml ارائه دهید. برای مثال، تنظیمات پنجره نمایش را ببینید.

در Android 17 و نسخه‌های بالاتر، پشتیبانی نمایشگر از تزئینات سیستم می‌تواند به‌صورت پویا تغییر کند. اگر نمایشگر پرچم FLAG_ALLOWS_CONTENT_MODE_SWITCH را داشته باشد، سیستم به کاربر اجازه می‌دهد تصمیم بگیرد که آیا نمایشگر میزبان برنامه‌ها باشد یا نمایشگر دیگری را آینه‌سازی کند. سیستم فقط درصورتی از تزئینات سیستم استفاده می‌کند که کاربر تصمیم بگیرد از نمایشگر برای میزبانی برنامه‌ها استفاده کند. اجزای سیستم، مانند «واسط کاربر سیستم» و راه‌اندازهای سازنده تجهیزات اصلی، مسئول ایجاد و نمایش تزئینات سیستم هستند. برای افزودن یا برداشتن تزئینات سیستم به‌صورت پویا، و برای مقداردهی اولیه یا آزاد کردن ساختارهای هر نمایشگر، این مؤلفه‌ها باید یک نمونه IDisplayWindowListener را ثبت کنند و روش‌های IDisplayWindowListener.onDisplayAddSystemDecorations و IDisplayWindowListener.onDisplayRemoveSystemDecorations را پیاده‌سازی کنند. ‫IDisplayWindowListener یک میانای برنامه‌سازی کاربردی پنهان است که فقط برای عناصر سیستم دردسترس است.

پیاده‌سازی

DisplayWindowSettings#setShouldShowSystemDecorsLocked همچنین در WindowManager#setShouldShowSystemDecors برای آزمایش نشان داده می‌شود. راه‌اندازی این روش با هدف فعال کردن تزئینات سیستم، پنجره‌های تزئینی را که قبلاً وجود نداشته‌اند اضافه نمی‌کند، یا اگر قبلاً وجود داشته‌اند آن‌ها را حذف نمی‌کند. در اکثر موارد، تغییر پشتیبانی از تزئینات سیستم فقط پس‌از بازراه‌اندازی دستگاه به‌طور کامل اعمال می‌شود.

بررسی‌های پشتیبانی از تزئینات سیستم در پایگاه کد WindowManager معمولاً ازطریق DisplayContent#supportsSystemDecorations انجام می‌شود، درحالی‌که بررسی‌های سرویس‌های خارجی (مثل «واسط کاربر سیستم» برای بررسی اینکه آیا نوار پیمایش باید نشان داده شود) از WindowManager#shouldShowSystemDecors استفاده می‌کنند. برای اینکه بفهمید این تنظیم چه چیزی را کنترل می‌کند، نقاط فراخوانی این روش‌ها را کاوش کنید.

پنجره‌های تزئینی میانای کاربر سیستم

‫Android 10 پشتیبانی از پنجره تزئینی سیستم را فقط برای نوار پیمایش اضافه می‌کند زیرا نوار پیمایش برای پیمایش بین فعالیت‌ها و برنامه‌ها ضروری است. به‌طور پیش‌فرض، نوار پیمایش امکانات «برگشت» و «صفحه اصلی» را نشان می‌دهد. نوار پیمایش فقط درصورتی گنجانده می‌شود که نمایشگر هدف از تزئینات سیستم پشتیبانی کند (به DisplayWindowSettings مراجعه کنید).

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

پنجره سیستم نمای کلی یا موارد اخیر در صفحه‌های دوم پشتیبانی نمی‌شود. در Android 10، «پروژه متن‌باز Android» فقط «موارد اخیر» را در نمایشگر پیش‌فرض نشان می‌دهد و شامل فعالیت‌های همه نمایشگرها است. وقتی از «موارد اخیر» راه‌اندازی شود، فعالیتی که در نمایشگر دوم بوده است به‌طور پیش‌فرض در نمایشگر جلو می‌آید. این رویکرد مشکلات شناخته‌شده‌ای دارد، مثلاً وقتی برنامه‌ها در صفحه‌های دیگر ظاهر می‌شوند، فوراً به‌روز نمی‌شود.

پیاده‌سازی

برای پیاده‌سازی ویژگی‌های اضافی «میانای کاربر سیستم»، سازندگان دستگاه باید از یک مؤلفه «میانای کاربر سیستم» استفاده کنند که به افزودن یا برداشتن نمایشگرها گوش می‌دهد و محتوای مناسب را ارائه می‌دهد.

عنصر «میانای کاربری سیستم» که از «چندنمایی» (MD) پشتیبانی می‌کند باید موارد زیر را مدیریت کند:

  • مقداردهی اولیه چند نمایشگر هنگام راه‌اندازی
  • نمایشگر در زمان اجرا اضافه شد
  • نمایشگر در زمان اجرا برداشته شد

وقتی «میانای کاربری سیستم» اضافه شدن نمایشگر را قبل‌از WindowManager تشخیص می‌دهد، شرایط مسابقه‌ای ایجاد می‌کند. می‌توانید با پیاده‌سازی یک برگشت تماس سفارشی از WindowManager به System UI هنگام اضافه شدن نمایشگر به‌جای مشترک شدن در DisplayManager.DisplayListener رویداد، از این مشکل جلوگیری کنید. برای پیاده‌سازی مرجع، CommandQueue.Callbacks#onDisplayAddSystemDecorations را برای پشتیبانی از نوار پیمایش و WallpaperManagerInternal#onDisplayAddSystemDecorations را برای کاغذدیواری‌ها ببینید.

علاوه‌براین، Android 10 این به‌روزرسانی‌ها را ارائه می‌دهد:

  • کلاس NavigationBarController همه عملکردهای مختص نوارهای پیمایش را کنترل می‌کند.
  • برای مشاهده نوار پیمایش سفارشی‌سازی‌شده، به CarStatusBar مراجعه کنید.
  • TYPE_NAVIGATION_BAR دیگر به یک نمونه محدود نیست و می‌توان از آن برای هر نمایشگر استفاده کرد.
  • ‫IWindowManager#hasNavigationBar به‌روزرسانی شده است تا پارامتر displayId را فقط برای «واسط کاربر سیستم» دربر بگیرد.

راه‌انداز

در Android 10، هر نمایشگری که برای پشتیبانی از تزئینات سیستم پیکربندی شده است، به‌طور پیش‌فرض دارای پشته صفحه اصلی اختصاصی برای فعالیت‌های راه‌انداز با نوع WindowConfiguration#ACTIVITY_TYPE_HOME است. هر نمایشگر از نمونه جداگانه‌ای از فعالیت راه‌انداز استفاده می‌کند:

شکل ۱. نمونه راه‌انداز چندنمایشگری برای platform/development/samples/MultiDisplay.

اکثر راه‌اندازهای موجود از چند نمونه پشتیبانی نمی‌کنند و برای اندازه‌های بزرگ صفحه‌نمایش بهینه‌سازی نشده‌اند. همچنین، اغلب نوع متفاوتی از تجربه در نمایشگرهای ثانویه/خارجی انتظار می‌رود. برای ارائه فعالیت اختصاصی برای صفحه‌نمایش‌های ثانویه، Android 10 دسته SECONDARY_HOME را در فیلترهای قصد معرفی کرد. نمونه‌های این فعالیت در همه نمایشگرهایی که از تزئینات سیستم پشتیبانی می‌کنند استفاده می‌شود، یک نمونه برای هر نمایشگر.

<activity>
    ...
    <intent-filter>
        <category android:name="android.intent.category.SECONDARY_HOME" />
        ...
    </intent-filter>
</activity>

فعالیت باید حالت راه‌اندازی‌ای داشته باشد که مانع از چند نمونه نشود و انتظار می‌رود با اندازه‌های مختلف صفحه‌نمایش سازگار شود. حالت راه‌اندازی نمی‌تواند singleInstance یا singleTask باشد.

پیاده‌سازی

در Android 10، RootActivityContainer#startHomeOnDisplayبسته به نمایشگری که صفحه اصلی در آن راه‌اندازی می‌شود، عنصر و هدف موردنظر به‌طور خودکار انتخاب می‌شود. RootActivityContainer#resolveSecondaryHomeActivity منطق جستجوی عنصر فعالیت راه‌انداز را براساس راه‌انداز انتخاب‌شده فعلی دربرمی‌گیرد و درصورت نیاز می‌تواند از پیش‌فرض سیستم استفاده کند (به ActivityTaskManagerService#getSecondaryHomeIntent مراجعه کنید).

محدودیت‌های امنیتی

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

کاغذدیواری

در Android 10 و نسخه‌های بالاتر، کاغذدیواری‌ها در نمایشگرهای ثانویه پشتیبانی می‌شوند:

شکل ۲. کاغذدیواری پویا در نمایشگر داخلی (بالا) و خارجی (پایین).

توسعه‌دهندگان می‌توانند با ارائه android:supportsMultipleDisplays="true" در تعریف XML WallpaperInfo، پشتیبانی از ویژگی کاغذدیواری را اعلام کنند. همچنین از توسعه‌دهندگان کاغذدیواری انتظار می‌رود که دارایی‌ها را بااستفاده از بافت نمایش در WallpaperService.Engine#getDisplayContext بار کنند.

چارچوب یک نمونه WallpaperService.Engine برای هر نمایشگر ایجاد می‌کند، بنابراین هر موتور سطح و بافت نمایشگر خود را دارد. توسعه‌دهنده باید مطمئن شود که هر موتور می‌تواند به‌طور مستقل، با نرخ فریم‌های مختلف، و با رعایت VSync ترسیم کند.

انتخاب کاغذدیواری برای هر صفحه

Android 10 پشتیبانی مستقیم پلاتفرم برای انتخاب کاغذدیواری برای صفحه‌نمایش‌های تکی ارائه نمی‌دهد. برای انجام این کار، به شناسه نمایشگر پایداری نیاز است تا تنظیمات کاغذدیواری برای هر نمایشگر حفظ شود. ‫Display#getDisplayId پویا است، بنابراین تضمینی وجود ندارد که نمایشگر فیزیکی پس‌از بازراه‌اندازی همان شناسه را داشته باشد.

بااین‌حال، Android 10 DisplayInfo.mAddress را اضافه کرد که شامل شناسه‌های پایدار برای نمایشگرهای فیزیکی است و می‌تواند برای پیاده‌سازی کامل در آینده استفاده شود. متأسفانه برای پیاده‌سازی منطق برای Android 10 خیلی دیر است. راه‌حل پیشنهادی:

  1. برای تنظیم کاغذدیواری‌ها، از کلاس WallpaperManager استفاده کنید.

    ‫WallpaperManager از شیء Context به‌دست می‌آید و هر شیء Context اطلاعاتی درباره نمایشگر مربوطه (Context#getDisplay/getDisplayId) دارد. بنابراین، می‌توانید displayId را از نمونه WallpaperManager بدون افزودن روش‌های جدید به‌دست آورید.

  2. در سمت چارچوب، از displayId به‌دست‌آمده از شیء Context استفاده کنید و آن را به شناسه ثابتی (مانند درگاه نمایشگر فیزیکی) نگاشت کنید. از شناسه ایستا برای حفظ کاغذدیواری انتخاب‌شده استفاده کنید.

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

اگر لازم است کاغذدیواری برای نمایشگری غیراز نمایشگر فعلی تنظیم شود، شیء Context جدیدی برای نمایشگر هدف (Context#createDisplayContext) ایجاد کنید و نمونه WallpaperManager را از آن نمایشگر دریافت کنید.

محدودیت‌های امنیتی

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

پیاده‌سازی

در Android 10، میاناهای IWallpaperConnection#attachEngine و IWallpaperService#attach پارامتر displayId را برای ایجاد اتصالات به‌ازای نمایشگر می‌پذیرند. ‫WallpaperManagerService.DisplayConnector موتور کاغذدیواری و اتصال هر نمایشگر را دربرمی‌گیرد. در WindowManager، کنترل‌کننده‌های کاغذدیواری برای هر شیء DisplayContent در ساختار ایجاد می‌شوند، به‌جای اینکه یک WallpaperController برای همه نمایشگرها وجود داشته باشد.

برخی‌از پیاده‌سازی‌های روش عمومی WallpaperManager (مانند WallpaperManager#getDesiredMinimumWidth) به‌روزرسانی شدند تا اطلاعات مربوط به نمایشگرهای متناظر را محاسبه و ارائه کنند. WallpaperInfo#supportsMultipleDisplays و مشخصه منبع مربوطه اضافه شده است تا توسعه‌دهندگان نرم‌افزار بتوانند گزارش دهند کدام کاغذدیواری‌ها برای چند صفحه‌نمایش آماده است.

اگر سرویس کاغذدیواری نشان‌داده‌شده در نمایشگر پیش‌فرض از نمایشگرهای متعدد پشتیبانی نکند، سیستم کاغذدیواری پیش‌فرض را در نمایشگرهای ثانویه نشان می‌دهد:

شکل ۳.‏ منطق بازگشت کاغذدیواری برای نمایشگرهای ثانویه.

فعال کردن پشتیبانی از کاغذدیواری پویا

در Android 10 و نسخه‌های بالاتر (API 29)، توسعه‌دهندگان می‌توانند از مشخصه android:supportsMultipleDisplays برای نشان دادن اینکه آیا تصویر زمینه‌شان می‌تواند در نمایشگرهای مختلف پخش شود یا نه استفاده کنند. در محیط‌های پردازش پنجره‌ای رایانه، که چندوظیفگی فشرده است، پرداز زنده تصاویر پس‌زمینه در نمایشگرهای خارجی می‌تواند تأثیر قابل‌توجهی بر سربار واحد پردازش گرافیکی و حافظه داشته باشد.

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

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

اگر سخت‌افزارتان می‌تواند چندین نمونه کاغذدیواری زنده را پرداز کند، پیکربندی زیر را ملغی کنید:

مسیر منبع frameworks/base/core/res/res/values/config.xml
نام پیکربندی config_isLiveWallpaperSupportedInDesktopExperience

سفارشی‌سازی کردن کاغذدیواری جایگزین

اگر کاغذدیواری‌های پویا غیرفعال باشند یا ارائه‌دهنده از آن‌ها پشتیبانی نکند، سیستم از مؤلفه پیش‌فرض استفاده می‌کند. می‌توانید این را به ارائه‌دهنده کاغذدیواری ثابت خودتان اشاره دهید:

مسیر منبع frameworks/base/core/res/res/values/config.xml
نام پیکربندی fallback_wallpaper_component

پیاده‌سازی پشتیبانی از کاغذدیواری

برای اعمال این تغییرات، از رونهاد منبع زمان ساخت در پوشه مختص دستگاهتان استفاده کنید که معمولاً device/<vendor>/<product>/overlay/frameworks/base/core/res/res/values/ است.