اعلان های دائمی مشترک

با شروع Android API سطح 26، اعلان‌های مداوم برای خدمات پیش‌زمینه مورد نیاز است. این الزام به منظور جلوگیری از مخفی کردن سرویس‌هایی است که ممکن است به منابع سیستم، از جمله باتری به‌ویژه، نیاز باشد. این الزام یک مشکل بالقوه ایجاد می‌کند: اگر برنامه‌ای با چندین سرویس پیش‌زمینه اعلان را به‌طور دقیق مدیریت نکند تا در همه سرویس‌ها به اشتراک گذاشته شود، چندین اعلان‌های غیرقابل رد کردن دائمی وجود خواهد داشت که منجر به درهم ریختگی نامطلوب در لیست فعال اعلان‌ها می‌شود.

این مشکل زمانی چالش‌برانگیزتر می‌شود که از SDK‌هایی مانند Navigation SDK استفاده می‌کنید، که سرویس‌های پیش‌زمینه مستقل از برنامه را اجرا می‌کنند، که می‌توانند اعلان‌های دائمی مستقل خود را داشته باشند و تلفیق آنها را دشوار می‌کند. برای رفع این مشکلات، Navigation SDK v1.11 یک API ساده برای کمک به مدیریت اعلان‌های دائمی در سراسر برنامه، از جمله درون SDK، معرفی کرد.

اعلان های مداوم را یکپارچه کنید

اجزاء

مدیر خدمات پیش زمینه یک بسته بندی در اطراف کلاس خدمات پیش زمینه اندروید و کلاس اعلان مداوم ارائه می دهد. عملکرد اصلی این بسته بندی استفاده مجدد از شناسه اعلان است به طوری که اعلان در تمام سرویس های پیش زمینه با استفاده از مدیر به اشتراک گذاشته می شود.


NavigationAPI شامل متدهای ایستا برای مقداردهی اولیه و دریافت Singleton ForegroundServiceManager است. این سینگل تنها یک بار در طول عمر Navigation SDK قابل تنظیم است. در نتیجه، اگر از یکی از فراخوان‌های اولیه استفاده می‌کنید ( initForegroundServiceManagerMessageAndIntent() یا initForegroundServiceManagerProvider() )، در صورتی که مسیر دوباره وارد شود، باید آن را با یک بلوک try/catch احاطه کنید. برای جلوگیری از مشکلات ناسازگاری، Navigation SDK یک استثنا در زمان اجرا ایجاد می‌کند، اگر یکی از روش‌ها را بیش از یک بار فراخوانی کنید، مگر اینکه ابتدا همه ارجاع‌ها به ForegroundServiceManager را پاک کنید و قبل از هر فراخوانی clearForegroundServiceManager() را فراخوانی کنید. در نسخه 2.0 Navigation SDK، برای این منظور یک استثنای علامت زده به API اضافه می شود.

چهار پارامتر initForegroundServiceManagerMessageAndIntent() application ، notificationId ، defaultMessage و resumeIntent هستند. اگر سه پارامتر نهایی تهی باشد، اعلان، اعلان Navigation SDK استاندارد است. هنوز هم می توان سایر خدمات پیش زمینه را در برنامه پشت این اعلان پنهان کرد. پارامتر notificationId شناسه اعلان را مشخص می کند که باید برای اعلان استفاده شود. اگر null باشد، از یک مقدار دلخواه استفاده می شود. می‌توانید آن را به صراحت تنظیم کنید تا تداخل‌ها را با سایر اعلان‌ها، مانند اعلان‌های SDK دیگر، برطرف کند. defaultMessage رشته ای است که وقتی سیستم در حال ناوبری نیست نمایش داده می شود. resumeIntent یک هدف است که با کلیک روی اعلان اجرا می شود. اگر resumeIntent پوچ باشد، کلیک روی اعلان نادیده گرفته می شود.

سه پارامتر initForegroundServiceManagerProvider() application ، notificationId و notificationProvider هستند. اگر دو پارامتر نهایی تهی باشند، اعلان، اعلان Navigation SDK استاندارد است. پارامتر notificationId شناسه اعلان را مشخص می کند که باید برای اعلان استفاده شود. اگر null باشد، از یک مقدار دلخواه استفاده می شود. می‌توانید آن را به صراحت تنظیم کنید تا تداخل‌ها را با سایر اعلان‌ها، مانند اعلان‌های SDK دیگر، برطرف کند. اگر notificationProvider تنظیم شده باشد، ارائه دهنده همیشه مسئول تولید اعلانی است که باید ارائه شود.

متد getForegroundServiceManager() Navigation SDK، مدیر سرویس پیش زمینه singleton را برمی گرداند. اگر هنوز یکی را ایجاد نکرده اید، معادل فراخوانی initForegroundServiceManagerMessageAndIntent() با پارامترهای null برای notificationId ، defaultMessage و resumeIntent است.

ForegroundServiceManager سه روش ساده دارد. دو مورد اول برای انتقال سرویس به داخل و خارج از پیش زمینه هستند و معمولاً از داخل سرویس ایجاد شده فراخوانی می شوند. استفاده از این روش ها تضمین می کند که سرویس ها با اعلان دائمی مشترک مرتبط هستند. متد نهایی، updateNotification() ، مدیر را نشان می‌دهد که اعلان تغییر کرده است و باید دوباره ارائه شود.

اگر خواهان کنترل کامل محتوای اعلان پایدار مشترک هستید، API جدید یک رابط NotificationContentProvider برای تعریف ارائه‌دهنده اعلان ارائه می‌کند که شامل یک روش واحد برای دریافت اعلان با محتوای فعلی است. همچنین یک کلاس پایه ارائه می دهد که می توانید به صورت اختیاری از آن برای کمک به تعریف ارائه دهنده استفاده کنید. یکی از اهداف اصلی کلاس پایه این است که ابزاری آسان برای فراخوانی updateNotification() بدون نیاز به دسترسی به ForegroundServiceManager فراهم می کند. اگر از نمونه ای از ارائه دهنده اعلان برای دریافت پیام های اعلان جدید استفاده می کنید، این روش کمکی می تواند مفید باشد، در این صورت می توانید مستقیماً با این روش داخلی تماس بگیرید تا پیام را در اعلان ارائه دهید.

سناریوهای استفاده

این بخش، سناریوهای استفاده برای استفاده از اعلان‌های دائمی مشترک را شرح می‌دهد.

اعلان‌های دائمی سایر سرویس‌های پیش‌زمینه برنامه را پنهان کنید
ساده ترین سناریو حفظ رفتار فعلی است و فقط از اعلان دائمی برای ارائه اطلاعات Navigation SDK استفاده کنید. سایر سرویس‌ها می‌توانند با استفاده از متدهای startForeground() و stopForeground() مدیر سرویس پیش‌زمینه، پشت این اعلان پنهان شوند.
اعلان‌های دائمی سایر سرویس‌های پیش‌زمینه برنامه را پنهان کنید، اما متن پیش‌فرض را تنظیم کنید که در صورت عدم پیمایش نشان داده شود
دومین سناریو ساده‌ترین حالت حفظ رفتار فعلی است و فقط از اعلان دائمی برای ارائه اطلاعات Navigation SDK استفاده کنید، مگر زمانی که سیستم در حال ناوبری نیست. هنگامی که سیستم در حال پیمایش نیست، رشته ارائه شده به initForegroundServiceManagerMessageAndIntent() به جای رشته پیش‌فرض Navigation SDK که «Google Maps» را ذکر می‌کند، نمایش داده می‌شود. این تماس همچنین می تواند برای تنظیم هدف رزومه استفاده شود که با کلیک روی اعلان فعال می شود.
کنترل کامل رندر اعلان مداوم را در دست بگیرید
سناریوی نهایی نیاز به تعریف و ایجاد یک ارائه دهنده اعلان و ارسال آن به 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() را زودتر فراخوانی کنید تا سناریوی استفاده مورد انتظار به خوبی تعریف شود. قبل از ایجاد یک Navigator جدید باید این متد را فراخوانی کنید.
  • در صورتی که مسیر کد بیش از یک بار وارد شود، حتماً استثنائات تماس‌های initForegroundServiceManagerMessageAndIntent() یا initForegroundServiceManagerProvider() را بگیرید. در Navigation SDK v2.0، فراخوانی چندین بار این روش، یک استثنا بررسی شده را به جای یک استثنا در زمان اجرا ایجاد می کند.
  • ممکن است Google هنوز برای داشتن یک استایل ثابت در طول عمر اعلان که با سبک سرصفحه مطابقت دارد، کاری انجام دهد.
  • وقتی ارائه‌دهنده اعلان را تعریف می‌کنید، می‌توانید رفتار heads-up را با اولویت کنترل کنید.
  • Google هنوز ابزار ساده ای برای بازیابی اطلاعات گام به گام ارائه نکرده است که ارائه دهنده اعلان ممکن است در اعلان درج کند.