Android के एपीआई लेवल 26 से, फ़ोरग्राउंड सेवाओं के लिए लगातार दिखने वाली सूचनाएं ज़रूरी हैं. इस शर्त का मकसद, आपको ऐसी सेवाओं को छिपाने से रोकना है जो सिस्टम के संसाधनों पर बहुत ज़्यादा दबाव डाल सकती हैं. इनमें खास तौर पर बैटरी शामिल है. इस ज़रूरी शर्त से एक समस्या हो सकती है: अगर फ़ोरग्राउंड में चलने वाली कई सेवाओं वाला कोई ऐप्लिकेशन, सूचना को इस तरह से मैनेज नहीं करता है कि उसे सभी सेवाओं के साथ शेयर किया जा सके, तो ऐसी सूचनाएं बार-बार दिख सकती हैं जिन्हें खारिज नहीं किया जा सकता. इससे सूचनाओं की चालू सूची में अनचाहा कॉन्टेंट इकट्ठा हो सकता है.
यह समस्या तब और भी मुश्किल हो जाती है, जब Navigation SDK जैसे एसडीके का इस्तेमाल किया जाता है. ये एसडीके, ऐप्लिकेशन से अलग फ़ोरग्राउंड सेवाएं चलाते हैं. साथ ही, इनकी अपनी अलग-अलग सूचनाएं होती हैं, जिन्हें एक साथ नहीं दिखाया जा सकता.
इन समस्याओं को हल करने के लिए, Navigation SDK v1.11 में एक आसान एपीआई पेश किया गया है. इससे ऐप्लिकेशन में लगातार दिखने वाली सूचनाओं को मैनेज करने में मदद मिलती है. इनमें एसडीके में दिखने वाली सूचनाएं भी शामिल हैं.
घटक
फ़ोरग्राउंड सेवा मैनेजर, Android फ़ोरग्राउंड सेवा क्लास और परसिस्टेंट सूचना क्लास के लिए रैपर उपलब्ध कराता है. इस रैपर का मुख्य काम, सूचना आईडी को फिर से इस्तेमाल करने के लिए लागू करना है, ताकि सूचना को मैनेजर का इस्तेमाल करने वाली सभी फ़ोरग्राउंड सेवाओं के साथ शेयर किया जा सके.
Navigation SDK में, ForegroundServiceManager
सिंगलटन को शुरू करने और पाने के लिए स्टैटिक तरीके शामिल होते हैं. इस सिंगलटन को Navigation SDK के लाइफ़टाइम में सिर्फ़ एक बार शुरू किया जा सकता है. इसलिए, अगर आपने किसी इनिशियलाइज़ेशन कॉल (initForegroundServiceManagerMessageAndIntent()
या initForegroundServiceManagerProvider()
) का इस्तेमाल किया है, तो आपको उसे try-catch ब्लॉक में रखना चाहिए, ताकि उस पाथ को फिर से ऐक्सेस किया जा सके. अगर आपने किसी भी तरीके को एक से ज़्यादा बार कॉल किया है, तो Navigation SDK रनटाइम अपवाद दिखाता है. हालांकि, ऐसा तब नहीं होता, जब आपने ForegroundServiceManager
के सभी रेफ़रंस पहले मिटा दिए हों और हर बार कॉल करने से पहले clearForegroundServiceManager()
को कॉल किया हो.
initForegroundServiceManagerMessageAndIntent()
के चार पैरामीटर ये हैं:
application
, notificationId
, defaultMessage
, और resumeIntent
. अगर आखिरी तीन पैरामीटर शून्य हैं, तो सूचना, Navigation SDK की स्टैंडर्ड सूचना होती है. हालांकि, इस सूचना के पीछे ऐप्लिकेशन की अन्य फ़ोरग्राउंड सेवाओं को अब भी छिपाया जा सकता है. notificationId
पैरामीटर, सूचना का वह आईडी तय करता है जिसका इस्तेमाल सूचना के लिए किया जाना चाहिए. अगर यह शून्य है, तो किसी भी वैल्यू का इस्तेमाल किया जाता है. इसे साफ़ तौर पर सेट किया जा सकता है, ताकि यह अन्य सूचनाओं के साथ टकराव से बच सके. जैसे, किसी अन्य SDK से मिलने वाली सूचनाएं. defaultMessage
एक स्ट्रिंग है. यह तब दिखती है, जब सिस्टम नेविगेट नहीं कर रहा होता है. resumeIntent
एक इंटेंट है. यह तब ट्रिगर होता है, जब सूचना पर क्लिक किया जाता है. अगर resumeIntent
की वैल्यू शून्य है, तो सूचना पर हुए क्लिक को अनदेखा कर दिया जाता है.
initForegroundServiceManagerProvider()
के तीन पैरामीटर ये हैं:
application
, notificationId
, और notificationProvider
. अगर आखिरी दो पैरामीटर शून्य हैं, तो सूचना, Navigation SDK की स्टैंडर्ड सूचना होती है. notificationId
पैरामीटर, सूचना के लिए इस्तेमाल किए जाने वाले सूचना आईडी के बारे में बताता है. अगर यह शून्य है, तो कोई भी वैल्यू इस्तेमाल की जाती है. इसे साफ़ तौर पर सेट किया जा सकता है, ताकि अन्य सूचनाओं (जैसे, किसी दूसरे SDK से मिलने वाली सूचनाएं) के साथ होने वाले टकराव से बचा जा सके. अगर notificationProvider
सेट है, तो सूचना जनरेट करने की ज़िम्मेदारी हमेशा सेवा देने वाली कंपनी की होती है.
Navigation SDK का getForegroundServiceManager()
तरीका, फ़ोरग्राउंड सेवा मैनेजर सिंगलेटन दिखाता है. अगर आपने अब तक कोई इवेंट जनरेट नहीं किया है, तो इसका मतलब है कि आपने notificationId
, defaultMessage
, और resumeIntent
के लिए, शून्य पैरामीटर के साथ initForegroundServiceManagerMessageAndIntent()
को कॉल किया है.
ForegroundServiceManager
के लिए, तीन आसान तरीके उपलब्ध हैं. पहले दो फ़ंक्शन, किसी सेवा को फ़ोरग्राउंड में लाने और फ़ोरग्राउंड से हटाने के लिए होते हैं. आम तौर पर, इन्हें बनाई गई सेवा के अंदर से कॉल किया जाता है. इन तरीकों का इस्तेमाल करने से यह पक्का किया जाता है कि सेवाएं, शेयर की गई परसिस्टेंट सूचना से जुड़ी हों. आखिरी तरीका, updateNotification()
, मैनेजर को यह सूचना देता है कि सूचना में बदलाव हुआ है और इसे फिर से रेंडर किया जाना चाहिए.
अगर आपको शेयर की गई परसिस्टेंट सूचना पर पूरा कंट्रोल चाहिए, तो एपीआई, सूचना देने वाली कंपनी को तय करने के लिए NotificationContentProvider
इंटरफ़ेस उपलब्ध कराता है. इसमें मौजूदा कॉन्टेंट के साथ सूचना पाने का एक तरीका होता है. यह एक बेस क्लास भी उपलब्ध कराता है. इसका इस्तेमाल करके, प्रोवाइडर को तय किया जा सकता है. बेस क्लास का मुख्य मकसद यह है कि यह updateNotification()
को ऐक्सेस किए बिना, updateNotification()
को कॉल करने का तरीका उपलब्ध कराता है.ForegroundServiceManager
अगर आपको सूचना के नए मैसेज पाने के लिए, सूचना देने वाली कंपनी के इंस्टेंस का इस्तेमाल करना है, तो सूचना में मैसेज रेंडर करने के लिए, इस इंटरनल तरीके को सीधे तौर पर कॉल किया जा सकता है.
इस्तेमाल के उदाहरण
इस सेक्शन में, शेयर की गई परसिस्टेंट सूचनाओं को इस्तेमाल करने के उदाहरण दिए गए हैं.
- दूसरे ऐप्लिकेशन की फ़ोरग्राउंड सेवाओं की लगातार दिखने वाली सूचनाएं छिपाएं
- सबसे आसान तरीका यह है कि मौजूदा व्यवहार को बनाए रखा जाए. साथ ही, Navigation SDK से मिली जानकारी को रेंडर करने के लिए, सिर्फ़ परसिस्टेंट सूचना का इस्तेमाल किया जाए. फ़ोरग्राउंड सेवा मैनेजर
startForeground()
औरstopForeground()
तरीकों का इस्तेमाल करके, अन्य सेवाएं इस सूचना के पीछे छिप सकती हैं. - अन्य ऐप्लिकेशन की फ़ोरग्राउंड सेवाओं की लगातार दिखने वाली सूचनाएं छिपाएं. हालांकि, नेविगेट न करने पर दिखने वाला डिफ़ॉल्ट टेक्स्ट सेट करें
- दूसरा सबसे आसान तरीका यह है कि मौजूदा व्यवहार को बनाए रखा जाए. साथ ही, Navigation SDK की जानकारी रेंडर करने के लिए सिर्फ़ परसिस्टेंट सूचना का इस्तेमाल किया जाए. हालांकि, ऐसा तब नहीं किया जाएगा, जब सिस्टम नेविगेट नहीं कर रहा हो. जब सिस्टम नेविगेट नहीं कर रहा होता है, तब
initForegroundServiceManagerMessageAndIntent()
को दी गई स्ट्रिंग दिखती है. इसके बजाय, Navigation SDK की डिफ़ॉल्ट स्ट्रिंग दिखती है, जिसमें "Google Maps" का ज़िक्र होता है. इस कॉल का इस्तेमाल, फिर से शुरू करने का इंटेंट सेट करने के लिए भी किया जा सकता है. यह इंटेंट, सूचना पर क्लिक करने पर ट्रिगर होता है. - स्थायी सूचना की रेंडरिंग का पूरा कंट्रोल पाएं
- आखिरी चरण में, सूचना देने वाली सेवा को तय करना और बनाना होता है. इसके बाद,
initForegroundServiceManagerProvider()
का इस्तेमाल करके, इसेForegroundServiceManager
को पास करना होता है. इस विकल्प से, आपको यह तय करने का पूरा कंट्रोल मिलता है कि सूचना में क्या रेंडर किया जाए. हालांकि, इससे 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()
को जल्द से जल्द कॉल करें, ताकि इस्तेमाल के संभावित उदाहरण को अच्छी तरह से तय किया जा सके. आपको नया नेविगेटर बनाने से पहले, इस तरीके को कॉल करना होगा.- अगर कोड पाथवे को एक से ज़्यादा बार डाला गया है, तो
initForegroundServiceManagerMessageAndIntent()
याinitForegroundServiceManagerProvider()
को कॉल करने पर होने वाली गड़बड़ियों को ठीक करें. Navigation SDK 2.0 में, इस तरीके को कई बार कॉल करने पर, रनटाइम एक्सेप्शन के बजाय चेक किया गया एक्सेप्शन दिखता है. - Google को अब भी सूचना के पूरे लाइफ़टाइम में, हेडर की स्टाइल से मेल खाने वाली स्टाइल को एक जैसा बनाए रखने के लिए काम करना पड़ सकता है.
- सूचना देने वाली सेवा को तय करते समय, प्राथमिकता के हिसाब से सूचनाओं को मैनेज किया जा सकता है.
- Google, बारी-बारी से दिशा-निर्देशों की जानकारी पाने का कोई आसान तरीका उपलब्ध नहीं कराता है. सूचना देने वाली कंपनी, सूचना में यह जानकारी डाल सकती है.