با شروع Android API سطح 26، اعلانهای مداوم برای خدمات پیشزمینه مورد نیاز است. این الزام به منظور جلوگیری از مخفی کردن سرویسهایی است که ممکن است به منابع سیستم، از جمله باتری بهویژه، نیاز باشد. این نیاز یک مشکل بالقوه ایجاد میکند: اگر برنامهای با چندین سرویس پیشزمینه، اعلان را بهطور دقیق مدیریت نکند تا در همه سرویسها به اشتراک گذاشته شود، در این صورت ممکن است چندین اعلان غیرقابل رد کردن دائمی وجود داشته باشد که منجر به درهم ریختگی نامطلوب در لیست فعال اعلانها شود.
این مشکل زمانی چالش برانگیزتر میشود که از SDKهایی مانند Navigation SDK استفاده میکنید، که سرویسهای پیشزمینه مستقل از برنامه را اجرا میکنند که اعلانهای دائمی مستقل خود را دارند و تلفیق آنها را دشوار میکند. برای رفع این مشکلات، Navigation SDK v1.11 یک API ساده برای کمک به مدیریت اعلانهای دائمی در سراسر برنامه، از جمله درون SDK، معرفی کرد.
اجزاء
مدیر خدمات پیش زمینه یک بسته بندی در اطراف کلاس خدمات پیش زمینه اندروید و کلاس اعلان مداوم ارائه می دهد. عملکرد اصلی این بسته بندی استفاده مجدد از شناسه اعلان است به طوری که اعلان در تمام سرویس های پیش زمینه با استفاده از مدیر به اشتراک گذاشته می شود.
Navigation SDK شامل متدهای ایستا برای مقداردهی اولیه و دریافت تکی ForegroundServiceManager
است. این سینگل تنها یک بار در طول عمر Navigation SDK قابل تنظیم است. در نتیجه، اگر از یکی از فراخوانهای اولیه استفاده میکنید ( initForegroundServiceManagerMessageAndIntent()
یا initForegroundServiceManagerProvider()
)، در صورتی که مسیر دوباره وارد شود، باید آن را با یک بلوک try-catch احاطه کنید. Navigation SDK یک استثنا در زمان اجرا ایجاد می کند اگر هر یک از روش ها را بیش از یک بار فراخوانی کنید، مگر اینکه ابتدا همه ارجاعات به ForegroundServiceManager
را پاک کنید و قبل از هر تماس بعدی clearForegroundServiceManager()
را فراخوانی کنید.
چهار پارامتر initForegroundServiceManagerMessageAndIntent()
application
، notificationId
، defaultMessage
و resumeIntent
هستند. اگر سه پارامتر نهایی تهی باشد، اعلان، اعلان Navigation SDK استاندارد است. هنوز هم می توان سایر خدمات پیش زمینه را در برنامه پشت این اعلان پنهان کرد. پارامتر notificationId
شناسه اعلان را مشخص می کند که باید برای اعلان استفاده شود. اگر null باشد، از یک مقدار دلخواه استفاده می شود. میتوانید آن را به صراحت تنظیم کنید تا تداخلها را با سایر اعلانها، مانند اعلانهای SDK دیگر، برطرف کند. defaultMessage
رشته ای است که وقتی سیستم در حال ناوبری نیست نمایش داده می شود. resumeIntent
یک هدف است که با کلیک روی اعلان اجرا می شود. اگر resumeIntent
پوچ باشد، کلیک روی اعلان نادیده گرفته می شود.
سه پارامتر initForegroundServiceManagerProvider()
application
، notificationId
و notificationProvider
هستند. اگر دو پارامتر نهایی تهی باشند، اعلان، اعلان Navigation SDK استاندارد است. پارامتر notificationId
شناسه اعلان را مشخص می کند که باید برای اعلان استفاده شود. اگر null باشد، از یک مقدار دلخواه استفاده می شود. میتوانید آن را به صراحت تنظیم کنید تا تداخلها را با سایر اعلانها، مانند اعلانهای SDK دیگر، برطرف کند. اگر notificationProvider
تنظیم شده باشد، ارائه دهنده همیشه مسئول تولید اعلانی است که باید ارائه شود.
متد Navigation SDK getForegroundServiceManager()
مدیر سرویس پیش زمینه 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 "";
}
}
}
بعد از اینکه NotificationContentProviderImpl
ایجاد کردید، Navigation SDK را با استفاده از کد زیر به آن متصل می کنید:
ForegroundServiceManager f = NavigationApi.getForegroundServiceManager(getApplication());
mNotification = new NotificationContentProviderImpl(getApplication());
NavigationApi.clearForegroundServiceManager();
NavigationApi.initForegroundServiceManagerProvider(getApplication(), null, mNotification);
هشدارها و برنامه های آینده
- حتماً
initForegroundServiceManagerMessageAndIntent()
یاinitForegroundServiceManagerProvider()
را زودتر فراخوانی کنید تا سناریوی استفاده مورد انتظار به خوبی تعریف شود. قبل از ایجاد یک Navigator جدید باید این متد را فراخوانی کنید. - در صورتی که مسیر کد بیش از یک بار وارد شود، حتماً استثنائات تماسهای
initForegroundServiceManagerMessageAndIntent()
یاinitForegroundServiceManagerProvider()
را بگیرید. در Navigation SDK v2.0، فراخوانی چندین بار این روش، یک استثنا بررسی شده را به جای یک استثنا در زمان اجرا ایجاد می کند. - ممکن است Google هنوز برای داشتن یک استایل ثابت در طول عمر اعلان که با سبک سرصفحه مطابقت دارد، کاری انجام دهد.
- وقتی ارائهدهنده اعلان را تعریف میکنید، میتوانید رفتار heads-up را با اولویت کنترل کنید.
- Google ابزار ساده ای برای بازیابی اطلاعات گام به گام ارائه نمی دهد که ارائه دهنده اعلان ممکن است در اعلان درج کند.