איחוד התראות בנייד

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

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

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

רכיבים

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


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

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

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

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

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

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

תרחישי שימוש

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

הסתרת התראות קבועות לגבי שירותים שפועלים בחזית של אפליקציות
התרחיש הקל ביותר הוא לשמר את ההתנהגות הנוכחית ולהשתמש רק התראה קבועה לעיבוד המידע של ה-Navigation SDK. שירותים נוספים אפשר להסתתר מאחורי ההתראה הזו באמצעות הכלי לניהול השירות שפועל בחזית startForeground() ו-stopForeground().
הסתרת התראות קבועות לגבי שירותים שפועלים בחזית של אפליקציות, אבל הגדרה טקסט ברירת המחדל שמוצג כשלא מתבצע ניווט
התרחיש השני הכי קל הוא לשמור על ההתנהגות הנוכחית, ולהשתמש בהתראה הקבועה רק כדי להציג מידע מ-Navigation SDK, מלבד במקרים שבהם המערכת לא מנווטת. כשהמערכת לא מנווטת, מופיעה המחרוזת שצוינה ב-initForegroundServiceManagerMessageAndIntent() במקום המחרוזת שמוגדרת כברירת מחדל ב-Navigation SDK ומזכירה את 'מפות Google'. אפשר גם להשתמש בקריאה הזו כדי להגדיר את הכוונה להמשך, שתופעל כשלוחצים על ההתראה.
שליטה מלאה על העיבוד של ההתראה הקבועה
התרחיש הסופי מחייב להגדיר וליצור ספק התראות ומעבירים אותו אל ForegroundServiceManager באמצעות initForegroundServiceManagerProvider(). האפשרות הזאת מספקת שליטה מלאה על מה שמוצג בהתראה, אבל גם מנתק את פרטי ההתראות של ה-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 "";
   }
 }
}

אחרי שיוצרים את NotificationContentProviderImpl, צריך לחבר את SDK לניווט אליו באמצעות הקוד הבא:

ForegroundServiceManager f = NavigationApi.getForegroundServiceManager(getApplication());
mNotification = new NotificationContentProviderImpl(getApplication());
NavigationApi.clearForegroundServiceManager();
NavigationApi.initForegroundServiceManagerProvider(getApplication(), null, mNotification);

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

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