תמיכה בסמלי המערכת

בדף הזה מפורטים העדכונים שבוצעו באזורים האלה שקשורים לתצוגה.

קישוטים של המערכת

ב-Android 10 נוספה תמיכה בהגדרת מסכים משניים להצגת קישוטים מסוימים של המערכת, כמו טפט, סרגל ניווט ומפעיל האפליקציות. כברירת מחדל, בתצוגה הראשית מוצגים כל העיטורים של המערכת, ובתצוגות המשניות מוצגים רק אלה שהופעלו. אפשר להגדיר תמיכה בעורך שיטות קלט (IME) בנפרד מקישוטי מערכת אחרים.

משתמשים ב-DisplayWindowSettings#setShouldShowSystemDecorsLocked כדי להוסיף תמיכה בעיטורי מערכת בתצוגה ספציפית או לספק ערך ברירת מחדל ב-/data/system/display_settings.xml. דוגמאות מופיעות במאמר בנושא הגדרות של חלון התצוגה.

הטמעה

DisplayWindowSettings#setShouldShowSystemDecorsLocked זמין גם ב-WindowManager#setShouldShowSystemDecors לבדיקה. הפעלת השיטה הזו במטרה להפעיל עיטורים של המערכת לא מוסיפה חלונות עיטור שנעלמו בעבר, ולא מסירה אותם אם הם היו קיימים בעבר. ברוב המקרים, השינוי בתמיכה בעיטורי מערכת נכנס לתוקף רק אחרי הפעלה מחדש של המכשיר.

בדרך כלל, בדיקות לתמיכה בעיטורי מערכת בבסיס הקוד של WindowManager מתבצעות באמצעות DisplayContent#supportsSystemDecorations, ובדיקות לשירותים חיצוניים (כמו System UI כדי לבדוק אם סרגל הניווט צריך להיות מוצג) מתבצעות באמצעות WindowManager#shouldShowSystemDecors. כדי להבין מה נשלט על ידי ההגדרה הזו, כדאי לבדוק את נקודות הקריאה של השיטות האלה.

חלונות עיצוב בממשק המשתמש של המערכת

ב-Android 10 נוספה תמיכה בחלון עיטור המערכת רק עבור סרגל הניווט, כי סרגל הניווט חיוני לניווט בין פעילויות ואפליקציות. כברירת מחדל, בסרגל הניווט מוצגים לחצני החזרה והבית. סרגל הניווט נכלל רק אם התצוגה של היעד תומכת בעיטורי מערכת (ראו DisplayWindowSettings).

שורת הסטטוס היא חלון מערכת מורכב יותר, כי היא כוללת גם את לוח ההתראות, את ההגדרות המהירות ואת מסך הנעילה. ב-Android 10, אין תמיכה בסרגל הסטטוס במסכים משניים. לכן, התראות, הגדרות ומסך נעילה מלא זמינים רק במסך הראשי.

חלון המערכת סקירה כללית או פריטים אחרונים לא נתמך במסכים משניים. ב-Android 10,‏ AOSP מציג את הכרטיסייה 'מהזמן האחרון' רק בתצוגת ברירת המחדל, והיא מכילה פעילויות מכל התצוגות. כשמפעילים פעילות שהייתה במסך משני מתוך 'האחרונים', היא מועברת לחזית של המסך הזה כברירת מחדל. לגישה הזו יש כמה בעיות ידועות, כמו אי-עדכון מיידי כשאפליקציות מופיעות במסכים אחרים.

הטמעה

כדי להטמיע תכונות נוספות של ממשק המשתמש של המערכת, יצרני מכשירים צריכים להשתמש ברכיב יחיד של ממשק המשתמש של המערכת שמקשיב להוספה או להסרה של תצוגות ומציג תוכן מתאים.

רכיב בממשק המשתמש של המערכת שתומך בתצוגה מרובת מסכים (MD) צריך לטפל במקרים הבאים:

  • אתחול של מסכים מרובים בזמן ההפעלה
  • התצוגה נוספת בזמן הריצה
  • התצוגה הוסרה בזמן הריצה

כשממשק המשתמש של המערכת מזהה הוספה של תצוגה לפני WindowManager, נוצר מרוץ תהליכים. כדי להימנע מכך, אפשר להטמיע קריאה חוזרת (callback) בהתאמה אישית מ-WindowManager לממשק המשתמש של המערכת כשמוסיפים תצוגה, במקום להירשם לאירועי DisplayManager.DisplayListener. למידע על הטמעה לדוגמה, אפשר לעיין במאמרים בנושא CommandQueue.Callbacks#onDisplayAddSystemDecorationsתמיכה בסרגל הניווט וWallpaperManagerInternal#onDisplayAddSystemDecorationsטפטים.

בנוסף, Android 10 כולל את העדכונים הבאים:

  • המחלקות NavigationBarController שולטות בכל הפונקציות שספציפיות לסרגלי ניווט.
  • כדי לראות סרגל ניווט בהתאמה אישית, אפשר לעיין במאמר בנושא CarStatusBar.
  • הסרטון TYPE_NAVIGATION_BAR כבר לא מוגבל למופע יחיד ואפשר להשתמש בו בכל מסך.
  • הפרמטר IWindowManager#hasNavigationBar מתעדכן וכולל את הפרמטר displayId רק בממשק המשתמש של המערכת.

מרכז האפליקציות

ב-Android 10, לכל מסך שמוגדר לתמיכה בעיטורי מערכת יש ערימת בית ייעודית לפעילויות של מרכז האפליקציות עם סוג WindowConfiguration#ACTIVITY_TYPE_HOME, כברירת מחדל. כל מסך משתמש במופע נפרד של פעילות מרכז האפליקציות:

איור 1. דוגמה להפעלה של אפליקציה במספר מסכים בפלטפורמה/פיתוח/דוגמאות/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 contains the logic to look up the launcher activity component depending on the currently selected launcher and can use the system default, if needed (see ActivityTaskManagerService#getSecondaryHomeIntent).

הגבלות אבטחה

בנוסף להגבלות שחלות על פעילויות במסכים משניים, כדי למנוע מצב שבו אפליקציה זדונית יוצרת מסך וירטואלי עם קישוטי מערכת מופעלים וקוראת מידע רגיש של משתמשים מהמשטח, מרכז האפליקציות מופיע רק במסכים וירטואליים שבבעלות המערכת. משגר האפליקציות לא מציג תוכן בצגים וירטואליים שאינם מערכתיים.

טפטים

ב-Android מגרסה 10 ואילך, יש תמיכה בטפטים במסכים משניים:

איור 2. טפט דינמי במסך הפנימי (למעלה) ובמסך החיצוני (למטה).

מפתחים יכולים להצהיר על תמיכה בתכונת הטפט על ידי הוספת התג android:supportsMultipleDisplays="true" בהגדרת ה-XML ‏WallpaperInfo. מפתחי טפטים צריכים גם לטעון נכסים באמצעות הקשר התצוגה ב-WallpaperService.Engine#getDisplayContext.

ה-framework יוצר מופע 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 ומאפיין משאב תואם נוספו, כדי שמפתחי אפליקציות יוכלו לדווח אילו טפטים מוכנים למסכים מרובים.

אם שירות הטפטים שמוצג בתצוגת ברירת המחדל לא תומך במסכים מרובים, המערכת מציגה את טפט ברירת המחדל במסכים המשניים:

איור 3. לוגיקה של טפט חלופי למסכים משניים.

הפעלת תמיכה בטפטים דינמיים

ב-Android 10 ומעלה (API 29), מפתחים יכולים להשתמש במאפיין android:supportsMultipleDisplays כדי לציין אם הטפט שלהם יכול להופיע על פני מסכים שונים. בסביבות של חלונות במחשב, שבהן יש הרבה משימות ריבוי, רינדור של טפטים דינמיים במסכים חיצוניים יכול להשפיע באופן משמעותי על העומס על ה-GPU ועל הזיכרון.

כדי לחסוך במשאבי המערכת, המערכת לא מציגה טפטים דינמיים במסכים מחוברים כברירת מחדל. כשטפט דינמי מוגבל על ידי הגדרת המערכת או מניפסט האפליקציה, המערכת מציגה טפט סטטי חלופי.

יצרני ציוד מקורי יכולים לשפר את החוויה הזו על ידי הפעלת תמיכה בטפטים מונפשים לחומרה מתקדמת, או על ידי התאמה אישית של טפט סטטי חלופי למראה ממותג.

אם החומרה יכולה לעבד כמה מקרים של טפטים דינמיים, צריך לבטל את ההגדרה הבאה:

נתיב המשאב 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/.