בגרסה 8.0 של Android הוספנו ארכיטקטורת מידע חדשה לאפליקציית ההגדרות כדי לפשט את אופן הארגון של ההגדרות ולאפשר למשתמשים למצוא במהירות הגדרות להתאמה אישית של מכשירי 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
DashboardFragment
הוא המארח של בקרי העדפות בסגנון פלאגין.
הפלח עובר בירושה מ-PreferenceFragment
ויש לו וו hooks להרחבה ולעדכון של רשימות העדפות סטטיות ודינמיות.
העדפות סטטיות
רשימת העדפות סטטית מוגדרת ב-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
יש הבדלים בהטמעה של 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
) היא שחתימת המבנה צריכה להתאים לאחת מהאפשרויות הבאות:
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
שמכיל את ההגדרה שרוצים להעביר ומאתרים את הרשומה Activity שמייצגת את ההגדרה הזו. - מגדירים את ערך המטא-נתונים של הפעילות בשדה
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 של ההעדפות של הדף. אפשר למצוא את המידע הזה ב-method 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 בהגדרות. כל הבדיקות הקיימות והחדשות אמורות לעבור.
- יוצרים ומתקינים את ההגדרות, ואז פותחים ידנית את הדף שרוצים לשנות. הדף אמור להתעדכן באופן מיידי.