Android API düzeyi 26'dan itibaren, ön plan hizmetleri için kalıcı bildirimler gereklidir. Bu şartın amacı, sistem kaynaklarına (özellikle de pile) aşırı yük bindirebilecek hizmetleri gizlemenizi önlemektir. Bu şart, olası bir soruna yol açar: Birden fazla ön plan hizmeti olan bir uygulama, bildirimi tüm hizmetlerde paylaşılacak şekilde dikkatli bir şekilde yönetmezse birden fazla kalıcı ve kapatılamayan bildirim olabilir. Bu da etkin bildirim listesinde istenmeyen bir karmaşaya neden olur.
Bu sorun, Navigation SDK gibi uygulamadan bağımsız ön plan hizmetleri çalıştıran ve kendi bağımsız kalıcı bildirimleri olan SDK'lar kullandığınızda daha da zorlaşır. Bu durum, bildirimleri birleştirmeyi zorlaştırır.
Navigasyon SDK'sı 1.11 sürümü, bu sorunları gidermek için SDK dahil olmak üzere uygulama genelinde kalıcı bildirimlerin yönetilmesine yardımcı olacak basit bir API sunar.

Bileşenler
Ön plan hizmet yöneticisi, Android ön plan hizmet sınıfı ve kalıcı bildirim sınıfı için bir sarmalayıcı sağlar. Bu sarmalayıcının ana işlevi, bildirim kimliğinin yeniden kullanılmasını zorunlu kılarak bildirimin, yöneticiyi kullanan tüm ön plan hizmetlerinde paylaşılmasını sağlamaktır.

Navigation SDK'sı, ForegroundServiceManager singleton'ını başlatmak ve almak için statik yöntemler içerir. Bu singleton, Navigation SDK'nın kullanım ömrü boyunca yalnızca bir kez başlatılabilir. Bu nedenle, başlatma çağrılarından birini (initForegroundServiceManagerMessageAndIntent() veya initForegroundServiceManagerProvider()) kullanırsanız bu yola yeniden girilmesi ihtimaline karşı çağrıyı bir try-catch bloğuyla çevrelemeniz gerekir. Navigation SDK, her bir yöntemi birden fazla kez çağırırsanız çalışma zamanı istisnası oluşturur. Bu istisnayı önlemek için önce ForegroundServiceManager ile ilgili tüm referansları temizlemeniz ve sonraki her çağrıdan önce clearForegroundServiceManager() yöntemini çağırmanız gerekir.
initForegroundServiceManagerMessageAndIntent() işlevinin dört parametresi şunlardır:
application, notificationId, defaultMessage ve resumeIntent. Son üç parametre boşsa bildirim, standart Navigation SDK bildirimidir. Uygulamadaki diğer ön plan hizmetlerini bu bildirimin arkasına gizlemek hâlâ mümkündür. notificationId parametresi, bildirim için kullanılması gereken bildirim kimliğini belirtir. Null ise rastgele bir değer kullanılır. Başka bir SDK'dan gelenler gibi diğer bildirimlerle çakışmaları önlemek için bunu açıkça ayarlayabilirsiniz. defaultMessage, sistem navigasyon yapmadığında gösterilen bir dizedir. resumeIntent, bildirime tıklandığında tetiklenen bir intent'tir. resumeIntent null ise bildirimin tıklanması yoksayılır.
initForegroundServiceManagerProvider() işlevinin üç parametresi
application, notificationId ve notificationProvider'dir. Son iki parametre boşsa bildirim, standart Navigation SDK bildirimidir. notificationId parametresi, bildirim için kullanılması gereken bildirim kimliğini belirtir. Boşsa rastgele bir değer kullanılır. Başka bir SDK'dan gelen bildirimler gibi diğer bildirimlerle çakışmaları önlemek için bunu açıkça ayarlayabilirsiniz. notificationProvider ayarlanırsa sağlayıcı, oluşturulacak bildirimi oluşturmaktan her zaman sorumludur.
Navigation SDK getForegroundServiceManager() yöntemi, ön plan hizmet yöneticisi singleton'ını döndürür. Henüz bir tane oluşturmadıysanız notificationId, defaultMessage ve resumeIntent için boş parametrelerle initForegroundServiceManagerMessageAndIntent() yöntemini çağırmakla aynıdır.
ForegroundServiceManager üç basit yöntemden oluşur. İlk ikisi, bir hizmeti ön plana taşımak ve ön plandan çıkarmak için kullanılır ve genellikle oluşturulan hizmetin içinden çağrılır. Bu yöntemlerin kullanılması, hizmetlerin paylaşılan kalıcı bildirimle ilişkilendirilmesini sağlar. Son yöntem olan updateNotification(), yöneticiye bildirimin değiştiğini ve yeniden oluşturulması gerektiğini bildirir.
Paylaşılan kalıcı bildirimin tam kontrolüne ihtiyacınız varsa API, geçerli içeriğe sahip bir bildirim almak için tek bir yöntem içeren bir bildirim sağlayıcı tanımlamak üzere NotificationContentProvider arayüzü sağlar. Ayrıca, sağlayıcıyı tanımlamanıza yardımcı olması için isteğe bağlı olarak kullanabileceğiniz bir temel sınıf da sağlar. Temel sınıfın ana amaçlarından biri, ForegroundServiceManager'e erişmeye gerek kalmadan updateNotification()'i çağırmanın bir yolunu sunmasıdır. Yeni bildirim mesajları almak için bildirim sağlayıcının bir örneğini kullanıyorsanız mesajı bildirimde oluşturmak için bu dahili yöntemi doğrudan çağırabilirsiniz.
Kullanım senaryoları
Bu bölümde, paylaşılan kalıcı bildirimlerin kullanım senaryoları ayrıntılı olarak açıklanmaktadır.
- Diğer uygulama ön plan hizmetlerinin kalıcı bildirimlerini gizleme
- En kolay senaryo, mevcut davranışı korumak ve kalıcı bildirimi yalnızca Navigasyon SDK'sı bilgilerini oluşturmak için kullanmaktır. Diğer hizmetler, ön plan hizmet yöneticisi
startForeground()vestopForeground()yöntemlerini kullanarak bu bildirimin arkasına gizlenebilir. - Diğer uygulama ön plan hizmetlerinin kalıcı bildirimlerini gizle ancak navigasyon kullanılmadığında gösterilen varsayılan metni ayarla
- İkinci en kolay senaryo, mevcut davranışı korumak ve kalıcı bildirimi yalnızca sistem gezinme yapmadığında Navigasyon SDK'sı bilgilerini oluşturmak için kullanmaktır. Sistem navigasyon yapmıyorken "Google Haritalar"dan bahseden varsayılan Navigasyon SDK'sı dizesi yerine
initForegroundServiceManagerMessageAndIntent()için sağlanan dize gösterilir. Bu çağrıyı, bildirim tıklandığında tetiklenen devam ettirme amacını ayarlamak için de kullanabilirsiniz. - Kalıcı bildirimin oluşturulması üzerinde tam kontrol sahibi olma
- Son senaryoda, bir bildirim sağlayıcı tanımlayıp oluşturmanız ve
initForegroundServiceManagerProvider()kullanarakForegroundServiceManageröğesine iletmeniz gerekir. Bu seçenek, bildirimde nelerin oluşturulacağı konusunda tam kontrol sağlar ancak Navigasyon SDK'sı bildirim bilgilerinin bildirimle bağlantısını keser ve bildirimde gösterilen faydalı adım adım talimatları kaldırır. Google, bu bilgileri alıp bildirime eklemek için basit bir yöntem sunmaz.
Örnek bildirim sağlayıcı
Aşağıdaki kod örneğinde, basit bir bildirim içerik sağlayıcısı kullanarak bildirimlerin nasıl oluşturulacağı ve döndürüleceği gösterilmektedir.
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 oluşturduktan sonra aşağıdaki kodu kullanarak Navigation SDK'yı buna bağlarsınız:
ForegroundServiceManager f = NavigationApi.getForegroundServiceManager(getApplication());
mNotification = new NotificationContentProviderImpl(getApplication());
NavigationApi.clearForegroundServiceManager();
NavigationApi.initForegroundServiceManagerProvider(getApplication(), null, mNotification);
Dikkat edilmesi gereken noktalar ve gelecek planları
- Beklenen kullanım senaryosunun iyi tanımlanması için
initForegroundServiceManagerMessageAndIntent()veyainitForegroundServiceManagerProvider()yöntemini erken çağırdığınızdan emin olun. Yeni bir Navigator oluşturmadan önce bu yöntemi çağırmanız gerekir. - Kod yoluna birden fazla kez girilmesi durumunda
initForegroundServiceManagerMessageAndIntent()veyainitForegroundServiceManagerProvider()çağrılarından kaynaklanan istisnaları yakaladığınızdan emin olun. Navigation SDK 2.0 sürümünde bu yöntemin birden çok kez çağrılması, çalışma zamanı istisnası yerine denetlenen bir istisna oluşturur. - Google'ın, bildirimin kullanım ömrü boyunca başlık stiliyle eşleşen tutarlı bir stil elde etmek için hâlâ yapması gereken işler olabilir.
- Bir bildirim sağlayıcı tanımladığınızda öncelik ile uyarı davranışını kontrol edebilirsiniz.
- Google, bildirim sağlayıcının bildirime ekleyebileceği adım adım bilgileri almak için basit bir yöntem sunmaz.