יצירת כרטיסי מידע מותאמים אישית בהגדרות המהירות לאפליקציה

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

חלונית ההגדרות המהירות כשמשבצת ה-VPN מופעלת
  הפעלה והשבתה
איור 1. חלונית ההגדרות המהירות כשמשבצת ה-VPN מופעלת פועלות ומכבות.

החלטה מתי ליצור כרטיס מידע

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

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

תרחישים לדוגמה במשבצת של אפליקציית כושר
איור 2. דוגמאות למשבצות מומלצות לעומת משבצות לא מומלצות באפליקציית כושר.

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

  • לא מומלץ להשתמש במשבצות כדי להפעיל אפליקציה. להשתמש בקיצור דרך לאפליקציה או בקיצור דרך רגיל במרכז האפליקציות.

  • לא מומלץ להשתמש במשבצות כדי לבצע פעולות חד-פעמיות של המשתמש. להשתמש בקיצור דרך של אפליקציה או התראה במקום זאת.

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

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

יצירת כרטיס מידע

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

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

יצירת סמל מותאם אישית

עליך לספק סמל מותאם אישית, שיוצג על גבי האריח חלונית ההגדרות. (הסמל הזה יתווסף להצהרה על TileService, שמתואר בקטע הבא.) הסמל חייב להיות לבן אחיד עם רקע שקוף, בגודל 24x24dp ובפורמט של VectorDrawable

דוגמה לכלי שרטוט וקטורי שניתן לשרטוט
איור 3. דוגמה לפריט וקטורי שניתן לשרטוט.

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

יצירה של שירות Salesforce Service והצהרה עליו

צריך ליצור שירות למשבצת שלך שמרחיב את הכיתה TileService.

Kotlin

class MyQSTileService: TileService() {

  // Called when the user adds your tile.
  override fun onTileAdded() {
    super.onTileAdded()
  }
  // Called when your app can update your tile.
  override fun onStartListening() {
    super.onStartListening()
  }

  // Called when your app can no longer update your tile.
  override fun onStopListening() {
    super.onStopListening()
  }

  // Called when the user taps on your tile in an active or inactive state.
  override fun onClick() {
    super.onClick()
  }
  // Called when the user removes your tile.
  override fun onTileRemoved() {
    super.onTileRemoved()
  }
}

Java

public class MyQSTileService extends TileService {

  // Called when the user adds your tile.
  @Override
  public void onTileAdded() {
    super.onTileAdded();
  }

  // Called when your app can update your tile.
  @Override
  public void onStartListening() {
    super.onStartListening();
  }

  // Called when your app can no longer update your tile.
  @Override
  public void onStopListening() {
    super.onStopListening();
  }

  // Called when the user taps on your tile in an active or inactive state.
  @Override
  public void onClick() {
    super.onClick();
  }

  // Called when the user removes your tile.
  @Override
  public void onTileRemoved() {
    super.onTileRemoved();
  }
}

יש להצהיר על TileService בקובץ המניפסט של האפליקציה. הוספת השם והתווית של TileService, הסמל המותאם אישית שיצרת בקטע הקודם, ואת ההרשאה המתאימה.

 <service
     android:name=".MyQSTileService"
     android:exported="true"
     android:label="@string/my_default_tile_label"  // 18-character limit.
     android:icon="@drawable/my_default_icon_label"
     android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
     <intent-filter>
         <action android:name="android.service.quicksettings.action.QS_TILE" />
     </intent-filter>
 </service>

ניהול השימוש ב-SpaceService

אחרי שיוצרים את TileService ומצהירים עליו בקובץ המניפסט של האפליקציה, לנהל את המצב.

TileService הוא שירות קשור. התוקף של TileService מוגבל כאשר בקשה מהאפליקציה או אם המערכת צריכה לתקשר איתה. טיפוסית מחזור החיים של bound-service כולל את ארבע השיטות הבאות של קריאה חוזרת: onCreate(), onBind(), onUnbind() וגם onDestroy(). השיטות האלה מופעלות על ידי המערכת בכל פעם נכנס לשלב חדש של מחזור חיים.

סקירה כללית של מחזור החיים של TileService

בנוסף לקריאות החוזרות (callback) ששולטות במחזור החיים של השירות המקושר, צריך להטמיע שיטות אחרות שספציפיות למחזור החיים של TileService. השיטות האלה ייתכן שניתן להתקשר מחוץ ל-onCreate() ול-onDestroy() מכיוון ש-Service השיטות של מחזור החיים וה-methods של מחזור החיים TileService נקראות בשני שרשורים אסינכרוניים נפרדים.

מחזור החיים של TileService כולל את השיטות הבאות שמופעלות על ידי המערכת בכל פעם שה-TileService נכנס לשלב חדש במחזור החיים:

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

  • onStartListening() ו-onStopListening(): השיטות האלה שנקראת בכל פעם שהאפליקציה מעדכנת את המשבצת, ומופיעה בה קריאה לעיתים קרובות. TileService עדיין מוגבל בין onStartListening() ל- onStopListening(), כך שהאפליקציה תוכל לשנות את הלחצן ולקבל עדכונים.

  • onTileRemoved(): השיטה הזו מופעלת רק אם המשתמש מסיר את הלחצן.

בחירת מצב האזנה

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

אין להניח ש-TileService יתקיים מחוץ ל-onStartListening() ו זוג onStopListening() של שיטות.

להשתמש במצב פעיל עבור TileService שמאזינים ועוקבים אחרי המצב שלו תהליך משלכם. ערך TileService במצב פעיל מוגבל ל-onTileAdded(), onTileRemoved(), מקישים על אירועים, וכשהתהליך של האפליקציה מבקש זאת.

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

אפשר לקרוא לשיטה הסטטית TileService.requestListeningState() לבקש את התחלת מצב ההאזנה ולקבל התקשרות חזרה אל onStartListening()

כדי להצהיר על מצב פעיל, צריך להוסיף את META_DATA_ACTIVE_TILE אל בקובץ המניפסט של האפליקציה.

<service ...>
    <meta-data android:name="android.service.quicksettings.ACTIVE_TILE"
         android:value="true" />
    ...
</service>

מצב לא פעיל

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

האפליקציה שלך תקבל התקשרות חזרה אל onStartListening() אחרי שהמשתמש פותח את חלונית ההגדרות המהירות. אפשר לעדכן את האובייקט Tile כמה פעמים בין onStartListening() ל-onStopListening().

אין צורך להצהיר על מצב לא פעיל – פשוט לא להוסיף META_DATA_ACTIVE_TILE לקובץ המניפסט של האפליקציה.

סקירה כללית של מצבי משבצות

אחרי שמשתמש מוסיף את המשבצת שלכם, היא תמיד קיימת באחד מהמצבים הבאים.

  • STATE_ACTIVE: מציין מצב מופעל או מופעל. המשתמש יכול לבצע אינטראקציה עם המשבצת שלכם במצב הזה.

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

  • STATE_INACTIVE: מציין מצב מושבת או מושהה. המשתמש יכול לבצע אינטראקציה עם המשבצת שלכם במצב הזה.

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

  • STATE_UNAVAILABLE: מציין מצב שאינו זמין באופן זמני. המשתמש לא יכול לבצע אינטראקציה עם המשבצת שלך במצב הזה.

    לדוגמה, המשמעות של אריח ב-STATE_UNAVAILABLE היא זמינים למשתמש מסיבה כלשהי.

המערכת מגדירה רק את המצב הראשוני של האובייקט Tile. הגדרת את Tile במצב של האובייקט במהלך שאר מחזור החיים שלו.

המערכת עשויה לבצע גוון את סמל המשבצת ואת הרקע כך שישקפו את מצב אובייקט Tile. Tile אובייקטים שהוגדרו לערך STATE_ACTIVE הם הכהים ביותר, עם STATE_INACTIVE ו-STATE_UNAVAILABLE נעשים יותר בהירים. הגוון המדויק הוא ספציפי ליצרן ולגרסה.

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

עדכון כרטיס המידע

אפשר יהיה לעדכן את משבצת השידור שלך כשתתבצע שיחה חוזרת אל onStartListening(). בהתאם למצב המשבצת, אפשר לעדכן את המשבצת לפחות פעם אחת עד מתקבלת שיחה חוזרת אל onStopListening().

במצב פעיל, אפשר לעדכן את כרטיס המידע פעם אחת בדיוק לפני שמקבלים קריאה חוזרת אל onStopListening(). במצב לא פעיל, אפשר לעדכן את כרטיס המידע בתור כמה פעמים שרוצים בין onStartListening() ל-onStopListening().

אפשר לאחזר את האובייקט Tile באמצעות קריאה ל-getQsTile(). לעדכון שדות ספציפיים של האובייקט Tile, מפעילים את השיטות הבאות:

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

Kotlin

data class StateModel(val enabled: Boolean, val label: String, val icon: Icon)

override fun onStartListening() {
  super.onStartListening()
  val state = getStateFromService()
  qsTile.label = state.label
  qsTile.contentDescription = tile.label
  qsTile.state = if (state.enabled) Tile.STATE_ACTIVE else Tile.STATE_INACTIVE
  qsTile.icon = state.icon
  qsTile.updateTile()
}

Java

public class StateModel {
  final boolean enabled;
  final String label;
  final Icon icon;

  public StateModel(boolean e, String l, Icon i) {
    enabled = e;
    label = l;
    icon = i;
  }
}

@Override
public void onStartListening() {
  super.onStartListening();
  StateModel state = getStateFromService();
  Tile tile = getQsTile();
  tile.setLabel(state.label);
  tile.setContentDescription(state.label);
  tile.setState(state.enabled ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
  tile.setIcon(state.icon);
  tile.updateTile();
}

ידית ברזים

המשתמשים יכולים להקיש על המשבצת שלך כדי לבצע פעולה אם המשבצת שלך STATE_ACTIVE או STATE_INACTIVE. לאחר מכן המערכת מפעילה את onClick() קריאה חוזרת (callback).

ברגע שהאפליקציה מקבלת קריאה חוזרת אל onClick(), היא יכולה להציג תיבת דו-שיח או פעילות, הפעלת עבודה ברקע או שינוי המצב של המשבצת שלכם.

Kotlin

var clicks = 0
override fun onClick() {
  super.onClick()
  counter++
  qsTile.state = if (counter % 2 == 0) Tile.STATE_ACTIVE else Tile.STATE_INACTIVE
  qsTile.label = "Clicked $counter times"
  qsTile.contentDescription = qsTile.label
  qsTile.updateTile()
}

Java

int clicks = 0;

@Override
public void onClick() {
  super.onClick();
  counter++;
  Tile tile = getQsTile();
  tile.setState((counter % 2 == 0) ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
  tile.setLabel("Clicked " + counter + " times");
  tile.setContentDescription(tile.getLabel());
  tile.updateTile();
}

הפעלה של תיבת דו-שיח

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

התחלת פעילות

startActivityAndCollapse() מתחיל פעילות תוך כיווץ של . הפעילויות מועילות אם יש מידע מפורט יותר שאפשר להציג מאשר בתיבת דו-שיח, או אם הפעולה היא אינטראקטיבית מאוד.

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

הקשה ארוכה על משבצת מציגה עבור המשתמש את המסך פרטי האפליקציה. כדי לשנות מברירת המחדל התנהגות זו, ובמקום זאת להפעיל פעילות להגדרת העדפות, <intent-filter> לאחת מהפעילויות שלך עם ACTION_QS_TILE_PREFERENCES.

החל מ-Android API 28, חובה ב-PendingIntent כוללים את Intent.FLAG_ACTIVITY_NEW_TASK:

if (Build.VERSION.SDK_INT >= 28) {
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}

אפשר גם להוסיף את הדגל ב-AndroidManifest.xml בקובץ ה- קטע Activity.

איך מסמנים משבצת שרוצים להחליף מצב

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

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

<service ...>
  <meta-data android:name="android.service.quicksettings.TOGGLEABLE_TILE"
    android:value="true" />
</service>

ביצוע פעולות בטוחות רק במכשירים שנעולים באופן מאובטח

יכול להיות שהמשבצת שלכם תוצג בחלק העליון של מסך הנעילה במכשירים נעולים. אם האריח מכיל מידע רגיש, יש לבדוק את הערך של isSecure() כדי כדי לקבוע אם המכשיר במצב מאובטח, וה-TileService צריך לשנות את ההתנהגות בהתאם.

אם בטוח לבצע את הפעולה של כרטיס המידע כשהוא נעול, משתמשים ב-startActivity() כדי להתחיל פעילות בחלק העליון של מסך הנעילה.

אם הפעולה בכרטיס המידע לא בטוחה, משתמשים ב-unlockAndRun() כדי לבקש מהמשתמש לבצע את הפעולות הבאות: לבטל את הנעילה של המכשיר. אם הפעולה בוצעה ללא שגיאות, המערכת תריץ את אובייקט Runnable שמעבירים .

להציג בקשה למשתמש להוסיף את כרטיס המידע

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

  1. מחליקים למטה כדי לפתוח את חלונית ההגדרות המהירות.
  2. מקישים על לחצן העריכה.
  3. גוללים בין כל כרטיסי המידע במכשיר עד שהם מאתרים את כרטיס המידע שלכם.
  4. מחזיקים את כרטיס המידע וגוררים אותו לרשימת המשבצות הפעילות.

המשתמש יכול גם להזיז או להסיר את המשבצת שלכם בכל שלב.

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

בקשת הגדרות מהירות של Location API
איור 5. הודעה על 'מיקום API' בהגדרות המהירות.
public void requestAddTileService (
  ComponentName tileServiceComponentName,
  CharSequence tileLabel,
  Icon icon,
  Executor resultExecutor,
  Consumer<Integer> resultCallback
)

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

חשוב להפעיל שיקול דעת כשאתם מחליטים מתי ובאיזו תדירות להציע למשתמשים בקשות. רביעי מומלץ להפעיל קריאה אל requestAddTileService() רק בהקשר – כמו כשהמשתמש יוצר אינטראקציה בפעם הראשונה עם תכונה שמופעלת במשבצת שלכם.

המערכת יכולה להפסיק לעבד בקשות עבור ComponentName אם המשתמש דחה אותה מספיק פעמים בעבר. המשתמש נקבע לפי Context שמשמש לאחזור השירות - הוא חייב להתאים למשתמש הנוכחי.