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

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

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

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

المكونات

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


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

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

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

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

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

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

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

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

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