ב-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
.
ארכיטקטורת מידע בסגנון פלאגין
כל פריט בהגדרות מיושם כ-Preference. אפשר להעביר בקלות העדפה מדף אחד לדף אחר.
כדי שיהיה קל יותר להעביר כמה הגדרות, ב-Android 8.0 הושק קטע מארח בסגנון פלאגין שמכיל את פריטי ההגדרות. הפריטים בהגדרות מוגדרים כבקרים בסגנון פלאגין. לכן, דף הגדרות מורכב מקטע מארח יחיד וממספר רכיבי בקרה של הגדרות.
קטע מרכז הבקרה
DashboardFragment
הוא המארח של בקרי העדפות בסגנון פלאגין.
החלק הקוד מקבל בירושה מ-PreferenceFragment
ויש לו הוקס להרחבה ולעדכון של רשימות העדפות סטטיות ודינמיות.
העדפות סטטיות
רשימת העדפות סטטית מוגדרת ב-XML באמצעות התג <Preference>
. בהטמעה של DashboardFragment
, משתמשים בשיטה getPreferenceScreenResId()
כדי להגדיר איזה קובץ XML מכיל את רשימת ההעדפות הסטטית שרוצים להציג.
העדפות דינמיות
פריט דינמי מייצג משבצת עם כוונה, שמובילה לנכס חיצוני או פנימי
פעילות. בדרך כלל, הכוונה מובילה לדף הגדרות אחר. לדוגמה, פריט ההגדרה 'Google' בדף הבית של ההגדרות הוא פריט דינמי. פריטים דינמיים מוגדרים ב-AndroidManifest
(כפי שמתואר בהמשך) ונטענים דרך FeatureProvider
(המוגדרת כ-
DashboardFeatureProvider
).
הגדרות דינמיות כבדות יותר מאשר מוגדרות באופן סטטי ולכן בדרך כלל מפתחים צריכים ליישם את ההגדרה כהגדרה סטטית. עם זאת, ההגדרה הדינמית יכולה להיות שימושית אם מתקיים אחד מהמצבים הבאים:
- ההגדרה לא מוטמעת ישירות באפליקציית ההגדרות (כמו החדרת הגדרה שהוטמעה על ידי אפליקציות של ספק או יצרן ציוד מקורי).
- ההגדרה אמורה להופיע בדף הבית של ההגדרות.
- כבר יש לכם פעילות להגדרה ואתם לא רוצים להטמיע את ההגדרה הסטטית הנוספת.
כדי להגדיר פעילות כהגדרה דינמית:
- כדי לסמן את הפעילות כהגדרה דינמית, מוסיפים לה מסנן 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()
של הפלח, כל הבקרים מופעלים בשיטה getAvailabilityStatus()
, ואם היא מחזירה true, מתבצעת הפעלה של displayPreference()
כדי לעבד את הלוגיקה של התצוגה.
getAvailabilityStatus()
חשוב גם להגדיר לאילו פריטים המערכת תציג תוצאות במהלך החיפוש.
PreferenceController במהדורות של Android 8.x
PreferenceController
מכיל את כל הלוגיקה ליצירת אינטראקציה עם ההעדפה, כולל הצגה, עדכון, הוספה לאינדקס החיפוש וכו'.
בהתאם לאינטראקציות עם ההעדפות, הממשק של
PreferenceController
כולל ממשקי API isAvailable()
,
displayPreference()
, handlePreferenceTreeClicked()
וכו'.
תוכלו למצוא תיעוד מפורט על כל API במחלקה של הממשק.
במהלך התקנת ההעדפה בחלק, מרכז הבקרה מספק שיטה לצרף PreferenceController
לפני זמן התצוגה. במהלך ההתקנה, הבקר מחובר לקטע כך שכל האירועים הרלוונטיים העתידיים נשלחים אליו.
ב-DashboardFragment
מופיעה רשימה של PreferenceControllers
במסך. ב-onCreate()
של החלק, כל הבקרים מופעלים לפונקציה isAvailable()
, ואם היא מחזירה את הערך true, הפונקציה displayPreference()
מופעלת כדי לעבד את הלוגיקה של התצוגה.
שימוש ב-DashboardFragment
העברת העדפה מדף א' לדף ב'
אם ההעדפה רשומה באופן סטטי ב-XML של ההעדפה של הדף המקורי יש לבצע את תהליך ההעברה הסטטי של מכשיר ה-Android גרסה בהמשך. אחרת, פועלים לפי נוהל ההעברה דינמי לגרסה ל-Android.
העברה סטטית ב-Android 9
- חיפוש קובצי ה-XML המועדפים לדף וליעד המקוריים
הדף הזה. אפשר למצוא את המידע הזה בדף
אמצעי תשלום אחד (
getPreferenceScreenResId()
). - מסירים את ההעדפה מה-XML של הדף המקורי.
- מוסיפים את ההעדפה ל-XML של דף היעד.
- מסירים את
PreferenceController
של ההעדפה הזו מהטמעת Java של הדף המקורי. בדרך כלל הוא נמצא ב-createPreferenceControllers()
. ייתכן שהבקר מוצהר ב- ישירות בפורמט XML.הערה: יכול להיות שההעדפה לא כוללת
PreferenceController
. - יצירת מופע של
PreferenceController
בדף היעדcreatePreferenceControllers()
. אםPreferenceController
מוגדר ב-XML בדף הישן, מגדירים אותו ב-XML של הדף החדש גם כן.
העברה דינמית ב-Android 9
- בודקים לאיזו קטגוריה שייכים דף היעד והדף המקורי. אפשר
אפשר למצוא את המידע הזה ב-
DashboardFragmentRegistry
. - יש לפתוח את הקובץ
AndroidManifest.xml
שמכיל את ההגדרה שבחרת תצטרכו לזוז ולמצוא את הרשומה 'פעילות' שמייצגת את ההגדרה הזו. - מגדירים את ערך המטא-נתונים של הפעילות בשדה
com.android.settings.category
למפתח הקטגוריה של הדף החדש.
מעבר סטטי בגרסאות Android 8.x
- מוצאים את קובצי ה-XML של ההעדפה לדף המקורי ולדף היעד. אפשר למצוא את המידע הזה בשיטה
- מסירים את ההעדפה ב-XML של הדף המקורי.
- מוסיפים את ההעדפה ל-XML של דף היעד.
- מסירים את הערך
PreferenceController
של ההעדפה הזו בהטמעת Java של הדף המקורי. בדרך כלל הקוד הואgetPreferenceControllers()
- יוצרים את
PreferenceController
ב-getPreferenceControllers()
של דף היעד.
getPreferenceScreenResId()
של הדף.
הערה: ייתכן שלהעדפה אין
PreferenceController
.
מעבר דינמי בגרסאות Android 8.x
- בודקים איזו קטגוריה מתארחת בדף המקורי ובדף היעד. המידע הזה מופיע ב-
DashboardFragmentRegistry
. - פותחים את הקובץ
AndroidManifest.xml
שמכיל את ההגדרה שרוצים להעביר ומאתרים את הרשומה Activity שמייצגת את ההגדרה הזו. - משנים את ערך המטא-נתונים של הפעילות עבור
com.android.settings.category
, הגדרת הערך של מפתח הקטגוריה של הדף החדש.
יצירת העדפה חדשה בדף
אם ההעדפה מופיעה באופן סטטי בקובץ ה-XML של ההעדפות של הדף המקורי, פועלים לפי התהליך הסטטי שמתואר בהמשך. אחרת, פועלים לפי התהליך הדינמי.
יצירת העדפה סטטית
- מוצאים את קובצי ה-XML המועדפים לדף. אפשר למצוא את המידע הזה. מהשיטה getPreferenceScreenResId() בדף.
- מוסיפים פריט Preference חדש ב-XML. חשוב לוודא שיש לו
android:key
ייחודי. -
מגדירים
PreferenceController
להעדפה הזו בשיטהgetPreferenceControllers()
של הדף.- ב-Android 8.x וב-Android 9 (אופציונלי), יוצרים מופע של
PreferenceController
עבור ההעדפה הזו ב-methodcreatePreferenceControllers()
של הדף.אם ההעדפה הזו כבר הייתה קיימת במקומות אחרים, יכול להיות שכבר יש לה
PreferenceController
. אפשר להשתמשPreferenceController
שוב בלי ליצור גרסת build חדשה. -
החל מ-Android 9, אפשר להצהיר על
PreferenceController
ב-XML ליד ההעדפה. לדוגמה:<Preference android:key="reset_dashboard" android:title="@string/reset_dashboard_title" settings:controller="com.android.settings.system.ResetPreferenceController"/>
- ב-Android 8.x וב-Android 9 (אופציונלי), יוצרים מופע של
יצירת העדפה דינמית
- בודקים לאיזו קטגוריה שייכים דף היעד והדף המקורי. המידע הזה מופיע ב-
DashboardFragmentRegistry
. - יצירת פעילות חדשה ב-
AndroidManifest
- מוסיפים את המטא-נתונים הנדרשים לפעילות החדשה כדי להגדיר את ההגדרה. מגדירים את ערך המטא-נתונים של
com.android.settings.category
לאותו ערך שהוגדר בשלב 1.
דף חדש
- יצירת מקטע חדש בירושה מ-
DashboardFragment
. - מגדירים את הקטגוריה שלו ב-
DashboardFragmentRegistry
.הערה: השלב הזה הוא אופציונלי. אם אתם לא צריכים העדפות דינמיות בדף הזה, אתם לא צריכים לספק מפתח קטגוריה.
- פועלים לפי השלבים להוספת ההגדרות הנדרשות לדף הזה. מידע נוסף זמין בקטע הטמעה.
אימות
- מריצים את בדיקות Robolectric בהגדרות. כל הבדיקות הקיימות והחדשות אמורות לעבור.
- יוצרים ומתקינים את ההגדרות, ואז פותחים באופן ידני את הדף שמשנים. הדף אמור להתעדכן באופן מיידי.