ארכיטקטורת מידע

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

דוגמאות ומקור

רוב הדפים בהגדרות מוטמעים כרגע באמצעות המסגרת החדשה. דוגמה טובה לכך היא DisplaySettings: packages/apps/Settings/src/com/android/settings/DisplaySettings.java

בהמשך מפורטים נתיבי הקבצים של רכיבים חשובים:

  • CategoryKey: packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
  • DashboardFragmentRegistry: packages/apps/Settings/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
  • DashboardFragment: packages/apps/Settings/src/com/android/settings/dashboard/DashboardFragment.java
  • AbstractPreferenceController: frameworks/base/packages/SettingsLib/src/com/android/settingslib/core/AbstractPreferenceController.java
  • BasePreferenceController (הושק ב-Android 9): packages/apps/Settings/src/com/android/settings/core/BasePreferenceController.java

הטמעה

אנחנו ממליצים ליצרני המכשירים להתאים את ארכיטקטורת המידע הקיימת של ההגדרות ולהוסיף דפי הגדרות נוספים לפי הצורך כדי להתאים לתכונות ספציפיות לשותפים. העברת ההעדפות מדף קודם (המוטמעת בתור SettingsPreferencePage) לדף חדש (שמוטמעת באמצעות DashboardFragment) יכולה להיות מורכבת. סביר להניח שההעדפה מהדף הקודם לא מוטמעת ב-PreferenceController.

לכן, כשמעבירים העדפות מדף מדור קודם לדף חדש, צריך ליצור PreferenceController ולהעביר את הקוד לבקר לפני שמפעילים אותו ב-DashboardFragment החדש. ממשקי ה-API שנדרשים ל-PreferenceController מתוארים בשם שלהם ומתועדים ב-Javadoc.

מומלץ מאוד להוסיף בדיקת יחידה לכל PreferenceController. אם השינוי נשלח אל AOSP, צריך לבצע בדיקת יחידה. לקבלת מידע נוסף על כתיבת מבחנים מבוססי-Robolectric, אפשר לעיין בקובץ ה-readme packages/apps/Settings/tests/robotests/README.md.

ארכיטקטורת מידע בסגנון יישומי פלאגין

כל פריט הגדרות מוטמע כהעדפה. ניתן להעביר העדפה בקלות מדף אחד לדף אחר.

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

קטע מרכז הבקרה

DashboardFragment הוא המארח של בקרי העדפות בסגנון יישומי פלאגין. המקטע יורש מ-PreferenceFragment ויש לו הוקים (hooks) להרחבה ולעדכון של רשימות העדפות סטטיות וגם רשימות של העדפות דינמיות.

העדפות סטטיות

רשימת העדפות סטטית מוגדרת ב-XML באמצעות התג <Preference>. הטמעה של DashboardFragment משתמשת בשיטה getPreferenceScreenResId() כדי להגדיר איזה קובץ XML מכיל את הרשימה הסטטית של ההעדפות להצגה.

העדפות דינמיות

פריט דינמי מייצג משבצת עם כוונה, שמובילה לפעילות חיצונית או פנימית. בדרך כלל, הכוונה מובילה לדף הגדרות שונה. לדוגמה, פריט ההגדרה "Google" בדף הבית של ההגדרות הוא פריט דינמי. פריטים דינמיים מוגדרים ב-AndroidManifest (בהמשך) ונטענים באמצעות FeatureProvider (מוגדר כ- DashboardFeatureProvider).

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

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

כדי להגדיר פעילות כהגדרה דינמית:

  • כדי לסמן את הפעילות כהגדרה דינמית, מוסיפים מסנן Intent לפעילות.
  • אומרים לאפליקציית ההגדרות לאיזו קטגוריה היא שייכת. הקטגוריה היא קבועה, והיא מוגדרת ב-CategoryKey.
  • אופציונלי: מוסיפים טקסט סיכום כשמוצגת ההגדרה.

הנה דוגמה מתוך אפליקציית ההגדרות עבור DisplaySettings.

<activity android:name="Settings$DisplaySettingsActivity"
                   android:label="@string/display_settings"
                   android:icon="@drawable/ic_settings_display">
             <!-- Mark the activity as a dynamic setting -->
              <intent-filter>
                     <action android:name="com.android.settings.action.IA_SETTINGS" />
              </intent-filter>
             <!-- Tell Settings app which category it belongs to -->
              <meta-data android:name="com.android.settings.category"
                     android:value="com.android.settings.category.ia.homepage" />
             <!-- Add a summary text when the setting is displayed -->
              <meta-data android:name="com.android.settings.summary"
                     android:resource="@string/display_dashboard_summary"/>
             </activity>

בזמן העיבוד, תוצג במקטע בקשה רשימה של העדפות גם מה-XML הסטטי וגם מההגדרות הדינמיות שנקבעו ב-AndroidManifest. גם אם ה-PreferenceController מוגדרים בקוד Java או ב-XML, DashboardFragment מנהל את לוגיקת הטיפול של כל הגדרה דרך PreferenceController (כפי שמפורט בהמשך). לאחר מכן הם מוצגים בממשק המשתמש כרשימה מעורבת.

בקר העדפות

יש הבדלים בין ההטמעה של PreferenceController ב-Android 9 וב-Android 8.x, כפי שמתואר בקטע הזה.

PreferenceController בגרסת Android 9

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

הממשק של PreferenceController מוגדר כ-BasePreferenceController. לדוגמה, ראו את הקוד packages/apps/Settings/src/com/android/settings/core/ BasePreferenceController.java

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

ל-BasePreferenceController יש ממשקי API כמו getAvailabilityStatus(), displayPreference(), handlePreferenceTreeClicked(), וכו'. מסמכי תיעוד מפורטים לכל API נמצאים ברמת הממשק.

הגבלה על הטמעת BasePreferenceController (ומחלקות המשנה שלו כמו TogglePreferenceController) היא שהחתימה של ה-constructor חייבת להתאים לאחת מהאפשרויות הבאות:

  • public MyController(Context context, String key) {}
  • public MyController(Context context) {}

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

DashboardFragment שומר רשימה של PreferenceController במסך. ב-onCreate() של המקטע, כל הבקרים מופעלים ל-method getAvailabilityStatus(). אם היא מחזירה True, המערכת מפעילה את displayPreference() כדי לעבד את לוגיקת התצוגה. getAvailabilityStatus() חשוב גם לציין למסגרת ההגדרות אילו פריטים זמינים במהלך החיפוש.

PreferenceController בגרסאות Android 8.x

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

בהתאם לאינטראקציות עם ההעדפות, בממשק של PreferenceController יש ממשקי API isAvailable(), displayPreference(), handlePreferenceTreeClicked() וכו'. אפשר למצוא תיעוד מפורט על כל API במחלקה של הממשק.

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

ב-DashboardFragment מופיעה רשימה של PreferenceControllers במסך. ב-onCreate() של המקטע, כל הבקרים מופעלים ל-method isAvailable(). אם מוחזר TRUE, מופעל displayPreference() כדי לעבד את לוגיקת התצוגה.

שימוש ב-DashboardFragment

העברת העדפה מדף א' לדף ב'

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

העברה סטטית ב-Android 9

  1. מוצאים את קובצי ה-XML המועדפים לדף המקורי ולדף היעד. המידע הזה מופיע ב-method getPreferenceScreenResId() של הדף.
  2. מסירים את ההעדפה מה-XML של הדף המקורי.
  3. מוסיפים את ההעדפה ל-XML של דף היעד.
  4. מסירים את המאפיין PreferenceController של ההעדפה הזו מההטמעה של Java בדף המקורי. בדרך כלל היא מוגדרת בcreatePreferenceControllers(). אפשר להצהיר על השלט רחוק ישירות ב-XML.

    הערה: יכול להיות שההעדפה לא כוללת PreferenceController.

  5. יוצרים מופע של PreferenceController ב-createPreferenceControllers() של דף היעד. אם הערך PreferenceController מוגדר ב-XML בדף הישן, צריך להגדיר אותו גם ב-XML עבור הדף החדש.

העברה דינמית ב-Android 9

  1. בודקים איזו קטגוריה מתארחת בדף המקורי ובדף היעד. תוכלו למצוא את המידע הזה ב-DashboardFragmentRegistry.
  2. פותחים את הקובץ AndroidManifest.xml שמכיל את ההגדרה שרוצים להעביר ומאתרים את הרשומה Activity שמייצגת את ההגדרה הזו.
  3. מגדירים את ערך המטא-נתונים של הפעילות עבור com.android.settings.category למפתח הקטגוריה של הדף החדש.

מעבר סטטי בגרסאות Android 8.x

  1. מוצאים את קובצי ה-XML של ההעדפה לדף המקורי ולדף היעד.
  2. המידע הזה מופיע בשיטה getPreferenceScreenResId() של הדף.
  3. מסירים את ההעדפה בקובץ ה-XML של הדף המקורי.
  4. מוסיפים את ההעדפה ל-XML של דף היעד.
  5. מסירים את המאפיין PreferenceController של ההעדפה הזו בהטמעה של Java של הדף המקורי. בדרך כלל המספר הוא getPreferenceControllers().
  6. הערה: יכול להיות שלהעדפה אין PreferenceController.

  7. יוצרים מופע של PreferenceController ב-getPreferenceControllers() של דף היעד.

מעבר דינמי בגרסאות Android 8.x

  1. בודקים איזו קטגוריה מתארחת בדף המקורי ובדף היעד. תוכלו למצוא את המידע הזה ב-DashboardFragmentRegistry.
  2. פותחים את הקובץ AndroidManifest.xml שמכיל את ההגדרה שרוצים להעביר ומאתרים את הרשומה Activity שמייצגת את ההגדרה הזו.
  3. משנים את ערך המטא-נתונים של הפעילות עבור com.android.settings.category ומגדירים את ערך הנקודה למפתח הקטגוריה של הדף החדש.

יצירת העדפה חדשה בדף

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

יצירת העדפה סטטית

  1. מוצאים את קובצי ה-XML המועדפים לדף. אפשר למצוא את המידע הזה במתודה getPreferenceScreenResId() בדף.
  2. מוסיפים פריט העדפה חדש ב-XML. חשוב לוודא שיש לו android:key ייחודי.
  3. מגדירים PreferenceController להעדפה הזו באמצעות method getPreferenceControllers() של הדף.
    • ב-Android 8.x ובאופן אופציונלי ב-Android 9, מגדירים PreferenceController להעדפה הזו ב-method createPreferenceControllers() של הדף.

      אם ההעדפה הזו כבר הייתה קיימת במקומות אחרים, יכול להיות שכבר יש בשבילה PreferenceController. אפשר להשתמש שוב ב-PreferenceController בלי ליצור אסימון חדש.

    • החל מ-Android 9, תוכלו להצהיר על PreferenceController ב-XML ליד ההעדפה. לדוגמה:
      <Preference
              android:key="reset_dashboard"
              android:title="@string/reset_dashboard_title"
              settings:controller="com.android.settings.system.ResetPreferenceController"/>
      

יצירת העדפה דינמית

  1. בודקים איזו קטגוריה מתארחת בדף המקורי ובדף היעד. תוכלו למצוא את המידע הזה ב-DashboardFragmentRegistry.
  2. יצירת פעילות חדשה ב-AndroidManifest
  3. כדי לקבוע את ההגדרה, צריך להוסיף את המטא-נתונים הדרושים לפעילות החדשה. מגדירים את ערך המטא-נתונים של com.android.settings.category לאותו ערך שמוגדר בשלב 1.

דף חדש

  1. יצירת מקטע חדש בירושה מ-DashboardFragment.
  2. מגדירים את הקטגוריה שלו ב-DashboardFragmentRegistry.

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

  3. פועלים לפי השלבים להוספת ההגדרות הנדרשות לדף הזה. מידע נוסף זמין בקטע הטמעה.

אימות

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