בניית מארח ווידג'טים

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

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

הנה סקירה כללית של המחלקות והמושגים העיקריים שקשורים להטמעה של AppWidgetHost בהתאמה אישית:

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

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

  • תצוגת המארח של הווידג'ט של האפליקציה: אפשר לחשוב על AppWidgetHostView כמסגרת שבה הווידג'ט עטוף בכל פעם שצריך להציג אותו. ווידג'ט משויך ל-AppWidgetHostView בכל פעם שהמארח מנפח את הווידג'ט.

    • כברירת מחדל, המערכת יוצרת AppWidgetHostView, אבל המארח יכול ליצור מחלקת משנה משלו של AppWidgetHostView על ידי הרחבה שלה.
    • החל מ-Android 12 (רמת API‏ 31), ‏ AppWidgetHostView מציג את ה-methods‏ setColorResources() ו-resetColorResources() לטיפול בצבעים שנטענים באופן דינמי. המארח אחראי לספק את הצבעים לשיטות האלה.
  • חבילת אפשרויות: AppWidgetHost משתמש בחבילת האפשרויות כדי להעביר מידע ל-AppWidgetProvider לגבי אופן הצגת הווידג'ט, למשל רשימת טווחי הגדלים, ואם הווידג'ט נמצא במסך הנעילה או במסך הבית. המידע הזה מאפשר ל-AppWidgetProvider להתאים את התוכן והמראה של הווידג'ט לפי האופן שבו הוא מוצג והמיקום שלו. אפשר להשתמש ב-updateAppWidgetOptions() וב-updateAppWidgetSize() כדי לשנות את החבילה של הווידג'ט. שתי השיטות האלה מפעילות את הקריאה החוזרת (callback) של onAppWidgetOptionsChanged() אל AppWidgetProvider.

ווידג'טים של קישור

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

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

<uses-permission android:name="android.permission.BIND_APPWIDGET" />

אבל זה רק השלב הראשון. בזמן הריצה, המשתמש חייב לתת לאפליקציה הרשאה מפורשת להוסיף ווידג'ט למארח. כדי לבדוק אם לאפליקציה יש הרשאה להוסיף את הווידג'ט, משתמשים ב-method‏ bindAppWidgetIdIfAllowed(). אם bindAppWidgetIdIfAllowed() מחזיר false, האפליקציה צריכה להציג תיבת דו-שיח שמבקשת מהמשתמש לתת הרשאה: "אישור" להוספת הווידג'ט הנוכחי, או "אישור תמידי" כדי לאשר את כל ההוספות העתידיות של הווידג'טים.

בקטע הקוד הבא אפשר לראות דוגמה לאופן שבו מציגים את תיבת הדו-שיח:

val intent = Intent(AppWidgetManager.ACTION_APPWIDGET_BIND).apply {
    putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
    putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.provider)
    // This is the options bundle described in the preceding section.
    putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options)
}
startActivityForResult(intent, REQUEST_BIND_APPWIDGET)

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

תחומי האחריות של המארחים

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

כל המארחים אחראים על:

  • כשמוסיפים ווידג'ט, מקצים את מזהה הווידג'ט כפי שמתואר למעלה. כשמסירים ווידג'ט מהמארח, צריך להפעיל את deleteAppWidgetId() כדי לבטל את ההקצאה של מזהה הווידג'ט.

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

  • במטא-נתונים של הווידג'טים AppWidgetProviderInfo מוגדרים רוחב וגובה כברירת מחדל. הערכים האלה מוגדרים בתאים – החל מ-Android 12, אם צוינו targetCellWidth ו-targetCellHeight – או ב-dp אם צוינו רק minWidth ו-minHeight. מאפייני גודל של ווידג'טים

    חשוב לוודא שהווידג'ט מוגדר עם מספר ה-dp הזה לפחות. לדוגמה, מארחים רבים מסדרים סמלים ורכיבים ברשת. בתרחיש הזה, כברירת מחדל המארח מוסיף ווידג'ט באמצעות מספר התאים המינימלי שעומד באילוצים של minWidth ו-minHeight.

טיפים לגישה שלכם

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

חבילת האפשרויות יכולה להכיל List<SizeF> שכולל את רשימת הגדלים האפשריים ב-dp שמופע של ווידג'ט יכול לקבל. מספר הגדלים שמופיעים תלוי בהטמעה של המארח. בדרך כלל, המארחים מספקים שני גדלים לטלפונים – לאורך ולרוחב – וארבעה גדלים למכשירים מתקפלים.

יש מגבלה של MAX_INIT_VIEW_COUNT (16) על מספר ה-RemoteViews השונים ש-AppWidgetProvider יכול לספק ל-RemoteViews. מכיוון שאובייקטים מסוג AppWidgetProvider ממפים אובייקט מסוג RemoteViews לכל גודל ב-List<SizeF>, אין לספק יותר מ-MAX_INIT_VIEW_COUNT גדלים.

כשמציינים בווידג'טים את המאפיינים maxResizeWidth ו-maxResizeHeight ב-dp, מומלץ שווידג'ט שמשתמש לפחות באחד מהמאפיינים האלה לא יחרוג מהגודל שצוין במאפיינים.

מקורות מידע נוספים

  • אפשר לעיין במאמרי העזרה של Glance.