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

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

קישוטי מערכת

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

הטמעה

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

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

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

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

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

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

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

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