התראות קבועות משותפות

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

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

איחוד ההתראות הקבועות

רכיבים

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


ה-API של הניווט מכיל שיטות סטטיות לאתחול ולקבלה של הסינגלטון ForegroundServiceManager. ניתן לאתחל את הסינגלטון הזה רק פעם אחת בכל משך החיים של ה-SDK של הניווט. לכן, אם אתם משתמשים באחת מקריאות האתחול (initForegroundServiceManagerMessageAndIntent() או initForegroundServiceManagerProvider()), עליכם להקיף אותה בבלוק test/catch כדי שהנתיב הזה יוזן מחדש. כדי למנוע בעיות של חוסר תאימות, ה-API של Navigation SDK מחריג את זמן הריצה אם מפעילים קריאה לכל אחת מהשיטות יותר מפעם אחת, אלא אם מסירים את כל ההפניות ל-ForegroundServiceManager וקוראים ל-clearForegroundServiceManager() לפני כל קריאה נוספת. בגרסה 2.0 של ה-SDK של הניווט, חריג מסומן נוסף ל-API למטרה הזו.

ארבעת הפרמטרים של initForegroundServiceManagerMessageAndIntent() הם application, notificationId, defaultMessage ו-resumeIntent. אם שלושת הפרמטרים האחרונים הם null, ההודעה היא ההודעה הרגילה של ה-SDK לניווט. עדיין אפשר להסתיר שירותים אחרים שפועלים בחזית באפליקציה שמאחורי ההתראה הזו. הפרמטר notificationId מציין את המזהה שבו יש להשתמש בהתראה. אם הוא null, אז נעשה שימוש בערך שרירותי. אפשר להגדיר אותה באופן מפורש כדי לעקוף התנגשויות עם התראות אחרות, כמו התראות מערכת SDK אחרת. הערך defaultMessage הוא מחרוזת שמוצגת כשהמערכת לא מנווטת. resumeIntent הוא Intent שמופעל כאשר לוחצים על ההתראה. אם הערך של resumeIntent הוא null, המערכת מתעלמת מהקליקים על ההתראה.

שלושת הפרמטרים של initForegroundServiceManagerProvider() הם application, notificationId ו-notificationProvider. אם שני הפרמטרים האחרונים הם null, ההודעה היא ההודעה הרגילה של ה-SDK לניווט. הפרמטר notificationId מציין את המזהה שבו יש להשתמש בהתראה. אם הוא null, אז נעשה שימוש בערך שרירותי. אפשר להגדיר אותה באופן מפורש כדי לעקוף התנגשויות עם התראות אחרות, כמו התראות מערכת SDK אחרת. אם השדה notificationProvider מוגדר, הספק תמיד אחראי ליצור את ההתראה שתוצג.

השיטה getForegroundServiceManager() של הניווט SDK מחזירה את הסינגלטון של מנהל השירות שפועל בחזית. אם עדיין לא יצרתם אותו, היא מקבילה לקריאה ל-initForegroundServiceManagerMessageAndIntent() עם פרמטרים ריקים עבור notificationId, defaultMessage ו-resumeIntent.

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

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

תרחישי שימוש

בקטע הזה מתוארים תרחישי השימוש לגבי השימוש בהתראות הקבועות המשותפות.

הסתרת ההתראות הקבועות לגבי שירותים אחרים שפועלים בחזית של האפליקציה
התרחיש הקל ביותר הוא לשמור על ההתנהגות הנוכחית ולהשתמש רק בהתראה הקבועה כדי לעבד את המידע מה-SDK של הניווט. שירותים אחרים יכולים להסתיר מאחורי ההתראה הזו באמצעות השימוש במנהל השירות שפועל בחזית startForeground() ובשיטות stopForeground().
הסתרת התראות קבועות על שירותים אחרים שפועלים בחזית של האפליקציה, אבל הגדרה של טקסט ברירת המחדל שיוצג כשלא מנווטים
התרחיש השני הקל ביותר הוא לשמור על ההתנהגות הנוכחית ולהשתמש רק בהתראה הקבועה לעיבוד מידע מה-SDK של הניווט, אלא אם המערכת לא מנווטת. כשהמערכת לא מנווטת, המחרוזת שסופקה ל-initForegroundServiceManagerMessageAndIntent() מוצגת במקום מחרוזת ברירת המחדל של ה-SDK לניווט, שמציינת את 'מפות Google'. ניתן להשתמש בשיחה הזו גם כדי להגדיר את כוונת המשך שתפעל כשלוחצים על ההתראה.
יש לך אפשרות לשלוט באופן מלא על אופן ההצגה של ההתראה הקבועה
בתרחיש האחרון יש להגדיר וליצור ספק התראות ולהעביר אותו אל ForegroundServiceManager דרך initForegroundServiceManagerProvider(). האפשרות הזו נותנת לכם שליטה מלאה על מה שמוצג בהתראה, אבל היא גם מנתקת את המידע על ההתראה של Navigation SDK מההתראה. כך אפשר להסיר את ההנחיות השימושיות של המסלול המפורט שמופיעות בהתראה. Google עדיין לא מספקת אמצעי פשוט לאחזור המידע הזה ולהוספתו להודעה.

דוגמה של ספק התראות

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

public class NotificationContentProviderImpl
   extends NotificationContentProviderBase
   implements NotificationContentProvider {
 private String channelId;
 private Context context;
 private String message;

 /** Constructor */
 public NotificationContentProviderImpl(Application application) {
   super(application);
   message = "-- uninitialized --";
   channelId = null;
   this.context = application;
 }

 /**
  * Sets message to display in the notification. Calls updateNotification
  * to display the message immediately.
  *
  * @param msg The message to display in the notification.
  */
 public void setMessage(String msg) {
   message = msg;
   updateNotification();
 }

 /**
  * Returns the notification as it should be rendered.
  */
 @Override
 public Notification getNotification() {
   Notification notification;

   if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
     Spanned styledText = Html.fromHtml(message, FROM_HTML_MODE_LEGACY);
     String channelId = getChannelId(context);
     notification =
         new Notification.Builder(context, channelId)
             .setContentTitle("Notifications Demo")
             .setStyle(new Notification.BigTextStyle()
                 .bigText(styledText))
             .setSmallIcon(R.drawable.ic_navigation_white_24dp)
             .setTicker("ticker text")
             .build();
   } else {
     notification = new Notification.Builder(context)
         .setContentTitle("Notification Demo")
         .setContentText("testing non-O text")
         .build();
   }

   return notification;
 }

 // Helper to set up a channel ID.
 private String getChannelId(Context context) {
   if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
     if (channelId == null) {
       NotificationManager notificationManager =
           (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
       NotificationChannel channel = new NotificationChannel(
           "default", "navigation", NotificationManager.IMPORTANCE_DEFAULT);
       channel.setDescription("For navigation persistent notification.");
       notificationManager.createNotificationChannel(channel);
       channelId = channel.getId();
     }
     return channelId;
   } else {
     return "";
   }
 }
}

אזהרות ותוכניות עתידיות

  • חשוב להתקשר ל-initForegroundServiceManagerMessageAndIntent() או ל-initForegroundServiceManagerProvider() לפני כן כדי שתרחיש השימוש הצפוי מוגדר בצורה טובה. צריך לקרוא לשיטה הזו לפני שיוצרים כלי ניווט חדש.
  • חשוב לשים לב לחריגים משיחות אל initForegroundServiceManagerMessageAndIntent() או אל initForegroundServiceManagerProvider() במקרה שנתיב הקוד הוזן יותר מפעם אחת. ב-API של הניווט בגרסה 2.0, הפעלת השיטה הזו מספר פעמים תגרום לחריג שנבדק ולא לחריג בזמן הריצה.
  • יכול להיות ש-Google עדיין תצטרך לעשות כדי לשמור על סגנון עקבי במשך משך החיים של ההתראה שיתאים לעיצוב הכותרת.
  • כשמגדירים ספק התראות, אפשר להשתמש בעדיפות.
  • Google עדיין לא מספקת אמצעי פשוט לאחזור מידע מפורט שספק התראות עשוי להוסיף להודעה.