دمج إشعارات الجوّال

بدءًا من المستوى 26 من واجهة برمجة تطبيقات Android، يجب إرسال إشعارات مستمرة للخدمات التي تعمل في المقدّمة. ويهدف هذا الشرط إلى منعك من إخفاء الخدمات التي قد تؤدي إلى زيادة الطلب على موارد النظام، بما في ذلك البطارية على وجه الخصوص. يؤدي هذا الشرط إلى حدوث مشكلة محتملة: إذا كان تطبيق مزوّد عدة خدمات تعمل في المقدّمة لا يدير الإشعار بعناية، بحيث تتم مشاركته عبر جميع الخدمات، قد تكون هناك إشعارات متكررة متعددة لا يمكن إغلاقها، ما يؤدي إلى حدوث فوضى غير مرغوب فيها في قائمة الإشعارات النشطة.

وتصبح هذه المشكلة أكثر صعوبة عند استخدام حِزم تطوير البرامج (SDK)، مثل "حزمة تطوير البرامج (SDK) الخاصة بالتنقل" التي تشغِّل خدمات تعمل في المقدّمة بشكل مستقل عن التطبيق الذي يتضمّن إشعارات مستقلة ومستقلة، ما يجعل من الصعب دمج هذه الحِزم. لمعالجة هذه المشاكل، قدّم الإصدار 1.11 من حزمة SDK الخاصة بالتنقل واجهة برمجة تطبيقات بسيطة للمساعدة في إدارة الإشعارات المتواصلة في التطبيق، بما في ذلك حزمة تطوير البرامج (SDK).

دمج الإشعارات المستمرة

المكوّنات

يوفّر مدير الخدمة التي تعمل في المقدّمة برنامج تضمين حول فئة خدمة Android التي تعمل في المقدّمة وفئة الإشعار الدائمة. وتتمثل الوظيفة الرئيسية لبرنامج التضمين في فرض إعادة استخدام "معرّف الإشعار" حتى تتم مشاركة الإشعار في جميع الخدمات التي تعمل في المقدّمة باستخدام المدير.


تحتوي حزمة تطوير البرامج (SDK) للتنقّل على طرق ثابتة لإعداد واستخدام ForegroundServiceManager سينغلتون. يمكن إعداد هذا النوع من المفردات مرة واحدة فقط في عمر حزمة SDK للتنقل. بناءً على ذلك، إذا كنت تستخدم أحد طلبات الإعداد (initForegroundServiceManagerMessageAndIntent() أو initForegroundServiceManagerProvider())، يجب إحاطته بمجموعة تجريبية في حال إعادة إدخال هذا المسار. تقدّم حزمة تطوير البرامج (SDK) الخاصة بالتنقل استثناءً في وقت التشغيل إذا استدعيت أيًا من الطريقتين أكثر من مرة ما لم يتم أولاً محو جميع الإشارات إلى ForegroundServiceManager والاستدعاء clearForegroundServiceManager() قبل كل استدعاء لاحق.

المَعلمات الأربع للسمة initForegroundServiceManagerMessageAndIntent() هي application وnotificationId وdefaultMessage وresumeIntent. إذا كانت المعلمات الثلاث الأخيرة فارغة، فعندئذ يكون الإشعار هو إشعار حزمة SDK للتنقل القياسي. ولا يزال من الممكن إخفاء الخدمات الأخرى التي تعمل في المقدّمة في التطبيق وراء هذا الإشعار. تحدّد المعلَمة notificationId معرّف الإشعار الذي يجب استخدامه للإشعار. إذا كانت قيمتها فارغة، فسيتم استخدام قيمة عشوائية. يمكنك ضبط هذا الإعداد بشكل صريح للتغلب على التعارضات مع الإشعارات الأخرى، مثل الإشعارات الواردة من حزمة تطوير برامج (SDK) أخرى. القيمة defaultMessage هي سلسلة يتم عرضها عندما يكون النظام لا يتنقّل. resumeIntent هو غرض يتم تنشيطه عند النقر على الإشعار. إذا كان resumeIntent فارغًا، سيتم تجاهل النقرات على الإشعار.

المَعلمات الثلاث للسمة initForegroundServiceManagerProvider() هي application وnotificationId وnotificationProvider. إذا كانت المعلمتان الأخيرتان فارغتين، يكون الإشعار هو إشعار SDK للتنقل القياسي. تحدّد المعلَمة notificationId معرّف الإشعار الذي يجب استخدامه للإشعار. إذا كانت قيمتها فارغة، فسيتم استخدام قيمة عشوائية. يمكنك ضبطها بشكل صريح لمعالجة التعارضات مع الإشعارات الأخرى، مثل الإشعارات الواردة من حزمة تطوير برامج (SDK) أخرى. إذا تم ضبط notificationProvider، يكون مقدّم الخدمة دائمًا مسؤولاً عن إنشاء الإشعار لعرضه.

تعرض طريقة حزمة SDK للتنقل getForegroundServiceManager() إدارة الخدمة التي تعمل في المقدّمة سيندلتون إذا لم تكن قد أنشأت مفتاحًا بعد، يمكنك استخدام طلب initForegroundServiceManagerMessageAndIntent() بمعلَمات فارغة للسمات notificationId وdefaultMessage وresumeIntent.

تتضمّن ForegroundServiceManager ثلاث طرق بسيطة. ويتمثل الخياران الأولان في نقل خدمة من المقدّمة وخارجها، وعادةً ما يتم استدعاءهما من داخل الخدمة التي تم إنشاؤها. يضمن استخدام هاتين الطريقتين ربط الخدمات بالإشعار الدائم المشترك. تُبلغ الطريقة النهائية، updateNotification()، المدير عن تغيير الإشعار، ويجب إعادة عرضه.

إذا كنت بحاجة إلى التحكّم الكامل في الإشعار الدائم المشترك، توفّر واجهة برمجة التطبيقات واجهة NotificationContentProvider لتحديد مقدّم الإشعارات، وهي طريقة واحدة لتلقّي إشعار يتضمّن المحتوى الحالي. كما أنه يوفر فئة أساسية يمكنك استخدامها اختياريًا للمساعدة في تحديد الموفر. أحد الأغراض الرئيسية للفئة الأساسية هو توفير طريقة لاستدعاء updateNotification() بدون الحاجة إلى الوصول إلى ForegroundServiceManager. إذا كنت تستخدم مثيلاً من مقدّم الإشعارات لتلقّي رسائل إشعارات جديدة، يمكنك استدعاء هذه الطريقة الداخلية مباشرةً لعرض الرسالة في الإشعار.

سيناريوهات الاستخدام

يوضّح هذا القسم سيناريوهات استخدام الإشعارات الدائمة المشتركة.

إخفاء الإشعارات المستمرة للخدمات التي تعمل في المقدّمة في التطبيقات الأخرى
تتمثّل أسهل سيناريو في الحفاظ على السلوك الحالي واستخدام الإشعار الدائم لعرض معلومات حزمة SDK الخاصة بالتنقل. ويمكن للخدمات الأخرى الاختباء خلف هذا الإشعار باستخدام مدير الخدمة التي تعمل في المقدّمة startForeground() وstopForeground().
إخفاء الإشعارات المستمرة للخدمات التي تعمل في المقدّمة في التطبيقات الأخرى، مع ضبط النص التلقائي الذي يظهر عند عدم التنقّل
ثاني أسهل سيناريو هو الحفاظ على السلوك الحالي، واستخدام الإشعار الدائم لعرض معلومات حزمة SDK الخاصة بالتنقل، باستثناء عندما يكون النظام لا يتنقل. عندما لا يتنقّل النظام، يتم عرض السلسلة المقدَّمة إلى initForegroundServiceManagerMessageAndIntent() بدلاً من سلسلة حزمة تطوير البرامج (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() مبكرًا لتحديد سيناريو الاستخدام المتوقّع بشكل جيد. ويجب استدعاء هذه الطريقة قبل إنشاء مستكشف جديد.
  • احرص على معرفة الاستثناءات من الطلبات إلى initForegroundServiceManagerMessageAndIntent() أو initForegroundServiceManagerProvider() في حال إدخال مسار الرمز أكثر من مرة. في الإصدار 2.0 من حزمة SDK الخاصة بالتنقل، يؤدي استدعاء هذه الطريقة عدة مرات إلى إنشاء استثناء محدّد بدلاً من استثناء وقت التشغيل.
  • قد يكون على Google تنفيذ بعض الإجراءات للحصول على تصميم متّسق على مدى فترة السماح بالإشعار الذي يطابق نمط العنوان.
  • عند تحديد مقدّم خدمة إشعارات، يمكنك التحكّم في سلوك التنبيه من خلال الأولوية.
  • لا توفّر Google وسيلة بسيطة لاسترداد المعلومات المفصّلة التي قد يدرجها مقدّم الإشعارات في الإشعار.