एंड्रॉइड में अग्रभूमि सेवा के लिए मैं सूचना पाठ कैसे अपडेट करूं?


133

मेरे पास एंड्रॉइड में एक अग्रभूमि सेवा सेटअप है। मैं अधिसूचना पाठ को अद्यतन करना चाहूंगा। मैं नीचे दिखाए गए अनुसार सेवा बना रहा हूं।

मैं इस अग्रभूमि सेवा के भीतर सेटअप सूचना पाठ को कैसे अपडेट कर सकता हूं? अधिसूचना अद्यतन करने के लिए सबसे अच्छा अभ्यास क्या है? किसी भी नमूना कोड की सराहना की जाएगी।

public class NotificationService extends Service {

    private static final int ONGOING_NOTIFICATION = 1;

    private Notification notification;

    @Override
    public void onCreate() {
        super.onCreate();

        this.notification = new Notification(R.drawable.statusbar, getText(R.string.app_name), System.currentTimeMillis());
        Intent notificationIntent = new Intent(this, AbList.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
        this.notification.setLatestEventInfo(this, getText(R.string.app_name), "Update This Text", pendingIntent);

        startForeground(ONGOING_NOTIFICATION, this.notification);

    }

मैं अपनी मुख्य गतिविधि में सेवा बना रहा हूँ जैसा कि नीचे दिखाया गया है:

    // Start Notification Service
    Intent serviceIntent = new Intent(this, NotificationService.class);
    startService(serviceIntent);

जवाबों:


61

मुझे लगता है कि startForeground()फिर से उसी यूनिक आईडी और Notificationनई जानकारी के साथ कॉल करने से काम चल जाएगा, हालांकि मैंने इस परिदृश्य की कोशिश नहीं की है।

अपडेट: टिप्पणियों के आधार पर, आपको अधिसूचना को अपडेट करने के लिए नोटिफिकेशन मैनजर का उपयोग करना चाहिए और आपकी सेवा अग्रभूमि मोड में बनी रहती है। नीचे दिए गए उत्तर पर एक नज़र डालें।


1
क्या आप कृपया मुझे एक उदाहरण दे सकते हैं कि मैं अपनी गतिविधि से इसे कैसे कहूंगा? मैं अपनी अग्रभूमि सेवा में विधियों को कॉल करने के तरीके के बारे में एक अच्छा नमूना नहीं ढूंढ सका हूं।
ल्यूक

1
@ ल्यूक: किसी सेवा का उपयोग करने के लिए कोई भी पैटर्न हैं, और मुझे नहीं पता कि आपका क्या अनुसरण है। यदि आप startService()सेवा को एक कमांड पास करने के लिए बुला रहे हैं , तो बस startService()फिर से कॉल करके यह बताएं कि इसका पाठ अपडेट किया जाए। या, यदि आप कॉल कर रहे हैं bindService(), तो सेवा को उसके पाठ को अपडेट करने के लिए अपने एपीआई में एक विधि जोड़ें। या, इस बात पर विचार करें कि क्या सेवा को ही निर्णय लेना चाहिए कि क्या पाठ को अद्यतन करना है या नहीं। या, शायद पाठ एक है SharedPeferenceकि सेवा में एक श्रोता है। अमूर्त में आपको सटीक सलाह देना असंभव है।
कॉमन्सवेयर

9
आगे स्पष्ट करने के लिए: आप cancel()द्वारा निर्धारित अधिसूचना नहीं कर सकते startForeground()। आपको स्वयं सेवा की अग्रभूमि स्थिति को निकालना होगा ( stopForeground()यदि आप टिकर पाठ बनाना चाहते हैं तो फिर से प्रकट हो सकते हैं। मैंने घंटों खो दिए क्योंकि इन उत्तरों ने मुझे विश्वास दिलाया कि यह वास्तव में संभव था।
slinden77

4
मैंने इस उत्तर को अस्वीकार कर दिया है क्योंकि यह स्पष्ट रूप से स्पष्ट गलत है: developer.android.com/training/notify-user/managing.html कृपया @CommonsWare इस उत्तर को हटाने पर विचार करें, क्योंकि आपका उच्च प्रतिष्ठा स्कोर इस उत्तर को "पवित्र सत्य" बनाता है: आकस्मिक ब्राउज़र। धन्यवाद।
HYS

2
मेरे लिए काम नहीं किया (हालांकि मैं पिछले परियोजना में इसी पद्धति का उपयोग करके याद करता हूं)। NotificationManagerजैसा कि मुझे उम्मीद थी, काम करना ।
user149408

224

जब आप startForeground () द्वारा निर्धारित अधिसूचना को अद्यतन करना चाहते हैं, तो बस एक नया संकेत बनाएँ और फिर इसे सूचित करने के लिए NotificationManager का उपयोग करें।

मुख्य बिंदु समान सूचना आईडी का उपयोग करना है।

मैंने अधिसूचना को अपडेट करने के लिए बार-बार कॉलिंग स्टार्टफोरग्राउंड () के परिदृश्य का परीक्षण नहीं किया, लेकिन मुझे लगता है कि NotificationManager.notify का उपयोग करना बेहतर होगा।

अधिसूचना को अपडेट करने से सेवा को अग्रभूमि स्थिति से नहीं हटाया जाएगा (यह केवल स्टॉपफ़ॉर्फ़ोन को कॉल करके किया जा सकता है);

उदाहरण:

private static final int NOTIF_ID=1;

@Override
public void onCreate (){
    this.startForeground();
}

private void startForeground() {
    startForeground(NOTIF_ID, getMyActivityNotification(""));
}

private Notification getMyActivityNotification(String text){
    // The PendingIntent to launch our activity if the user selects
    // this notification
    CharSequence title = getText(R.string.title_activity);
    PendingIntent contentIntent = PendingIntent.getActivity(this,
            0, new Intent(this, MyActivity.class), 0);

    return new Notification.Builder(this)
            .setContentTitle(title)
            .setContentText(text)
            .setSmallIcon(R.drawable.ic_launcher_b3)
            .setContentIntent(contentIntent).getNotification();     
}

/**
 * This is the method that can be called to update the Notification
 */
private void updateNotification() {
    String text = "Some text that will update the notification";

    Notification notification = getMyActivityNotification(text);

    NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    mNotificationManager.notify(NOTIF_ID, notification);
}

प्रलेखन राज्यों

एक अधिसूचना सेट करने के लिए इसे अपडेट किया जा सकता है, इसे कॉल करके अधिसूचना आईडी जारी करें NotificationManager.notify()। आपके द्वारा इसे जारी करने के बाद इस अधिसूचना को अद्यतन करने के लिए, एक NotificationCompat.Builderवस्तु का अद्यतन या निर्माण करें, उससे एक वस्तु का निर्माण करें Notification, और Notificationउसी आईडी के साथ जारी करें जिसे आपने पहले इस्तेमाल किया था। यदि पिछली अधिसूचना अभी भी दिखाई देती है, तो सिस्टम इसे Notificationऑब्जेक्ट की सामग्री से अपडेट करता है । यदि पिछली अधिसूचना को खारिज कर दिया गया है, तो इसके बजाय एक नई अधिसूचना बनाई जाती है।


35
यह सही जवाब है! ऊपर दिया गया उत्तर बहुत गलत और भ्रामक है। आपको अपनी सेवा को पुनः आरंभ करने की आवश्यकता नहीं है, इसलिए आप एक मूर्खतापूर्ण अधिसूचना को अपडेट करें।
राडू

7
@Radu जबकि मैं मानता हूं कि यह इष्टतम उत्तर है (यह कॉमन्सवेयर के उत्तर द्वारा लिए गए थोड़े लंबे कोड-पथ से बचा जाता है) आप गलत हैं कि कॉमन्सवेयर का उत्तर क्या करता है - स्टार्ट / स्टॉपफॉरगाउंड सेवा शुरू / बंद नहीं करते हैं, वे सिर्फ इसके अग्रभूमि को प्रभावित करते हैं। ।
स्टीव

@ स्टीवी उस स्टेवी के लिए धन्यवाद, आप शायद सही हैं। फिर भी मैं उस के साथ खिलवाड़ नहीं करूंगा!
राडु

कॉलिंग notify()या startForeground()दोनों कॉल करने के लिए नेतृत्व करते हैं onStartCommand()
एम। रेजा नासिरलू

10
के साथ NotificationManagerदिखाए गए एक अधिसूचना को अपडेट करने के लिए उपयोग करने में समस्या यह startForegroundहै कि कॉलिंग stopForegroundअब अधिसूचना को नहीं हटाएगी। startForegroundउस समस्या को कम करने के लिए इसे दूसरे कॉल के साथ अपडेट करना ।
ताड

21

एंड्रॉइड 8.0+ में Luca Manzo जवाब पर सुधार करते समय अधिसूचना को अपडेट करते समय यह ध्वनि और हेड-अप के रूप में दिखाएगा।
जिसे रोकने के लिए आपको जोड़ना होगाsetOnlyAlertOnce(true)

तो कोड है:

private static final int NOTIF_ID=1;

@Override
public void onCreate(){
        this.startForeground();
}

private void startForeground(){
        startForeground(NOTIF_ID,getMyActivityNotification(""));
}

private Notification getMyActivityNotification(String text){
        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
        ((NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(
        NotificationChannel("timer_notification","Timer Notification",NotificationManager.IMPORTANCE_HIGH))
}

        // The PendingIntent to launch our activity if the user selects
        // this notification
        PendingIntent contentIntent=PendingIntent.getActivity(this,
        0,new Intent(this,MyActivity.class),0);

        return new NotificationCompat.Builder(this,"my_channel_01")
        .setContentTitle("some title")
        .setContentText(text)
        .setOnlyAlertOnce(true) // so when data is updated don't make sound and alert in android 8.0+
        .setOngoing(true)
        .setSmallIcon(R.drawable.ic_launcher_b3)
        .setContentIntent(contentIntent)
        .build();
}

/**
 * This is the method that can be called to update the Notification
 */
private void updateNotification(){
        String text="Some text that will update the notification";

        Notification notification=getMyActivityNotification(text);

        NotificationManager mNotificationManager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(NOTIF_ID,notification);
}

आपने मेरा दिन बचाया। धन्यवाद
रुबेन Viguera

1
मिसिंग कीवर्ड, वहाँ होना चाहिएnew NotificationChannel
7

5

यहां आपकी सेवा में ऐसा करने का कोड है । एक नया नोटिफिकेशन बनाएं, लेकिन सूचना प्रबंधक से उसी अधिसूचना आईडी को अधिसूचित करने के लिए कहें, जिसका उपयोग आपने शुरू में किया था।

Notification notify = createNotification();
final NotificationManager notificationManager = (NotificationManager) getApplicationContext()
    .getSystemService(getApplicationContext().NOTIFICATION_SERVICE);

notificationManager.notify(ONGOING_NOTIFICATION, notify);

पूर्ण नमूना कोड के लिए, आप यहां देख सकते हैं:

https://github.com/plateaukao/AutoScreenOnOff/blob/master/src/com/danielkao/autoscreenonoff/SensorMonitorService.java


मुझे यकीन नहीं है कि यह startService के अग्रभूमि की स्थिति को बनाए रखेगा।
मार्टिन मार्कोसिनी

@ डैनियल काओ आपका समाधान अग्रभूमि सेवा शुरू नहीं करता है
इगोरगानापोलस्की

4
मुझे सही करें अगर मैं गलत हूं, लेकिन क्या लोग इस जवाब को वोट दे सकते हैं कि कृपया इसके बारे में अधिक विवरणात्मक हो सकता है कि इसमें क्या गलत है? सवाल यह नहीं पूछता है कि फोरग्राउंड सेवा कैसे शुरू की जाए, बल्कि एक अग्रभूमि सेवा की अधिसूचना को कैसे अपडेट किया जाए। यह लुका के रूप में प्रभावी रूप से एक ही उत्तर है जिसे लोग काम करने के लिए सहमत हैं और अग्रभूमि की स्थिति बनाए रखते हैं।
आईआईटी

@ यह काम नहीं करता है। संदेश के not foregroundलिए अधिसूचना की स्थिति बन जाती है foreground created
व्याचेस्लाव

1
यह एक डुप्लिकेट अधिसूचना के परिणामस्वरूप होता है, क्योंकि startForeground () पहले से ही कहा जाता था।
इगोरगानापोलस्की

2

ऐसा लगता है कि मौजूदा जवाबों में से कोई भी नहीं दिखाता है कि पूरा मामला कैसे संभालना है - अगर यह पहली कॉल है, तो शुरू करने के लिए, लेकिन बाद की कॉल के लिए अधिसूचना को अपडेट करें।

सही स्थिति का पता लगाने के लिए आप निम्नलिखित पैटर्न का उपयोग कर सकते हैं:

private void notify(@NonNull String action) {
    boolean isForegroundNotificationVisible = false;
    NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    StatusBarNotification[] notifications = notificationManager.getActiveNotifications();
    for (StatusBarNotification notification : notifications) {
        if (notification.getId() == FOREGROUND_NOTE_ID) {
            isForegroundNotificationVisible = true;
            break;
        }
    }
    Log.v(getClass().getSimpleName(), "Is foreground visible: " + isForegroundNotificationVisible);
    if (isForegroundNotificationVisible){
        notificationManager.notify(FOREGROUND_NOTE_ID, buildForegroundNotification(action));
    } else {
        startForeground(FOREGROUND_NOTE_ID, buildForegroundNotification(action));
    }
}

इसके अलावा आपको अधिसूचना और चैनल को अन्य उत्तरों की तरह बनाने की आवश्यकता है:

private Notification buildForegroundNotification(@NonNull String action) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        createNotificationChannel();
    }
    //Do any customization you want here
    String title;
    if (ACTION_STOP.equals(action)) {
        title = getString(R.string.fg_notitifcation_title_stopping);
    } else {
        title = getString(R.string.fg_notitifcation_title_starting);
    }
    //then build the notification
    return new NotificationCompat.Builder(this, CHANNEL_ID)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle(title)
            .setOngoing(true)
            .build();
}

@RequiresApi(Build.VERSION_CODES.O)
private void createNotificationChannel(){
    NotificationChannel chan = new NotificationChannel(CHANNEL_ID, getString(R.string.fg_notification_channel), NotificationManager.IMPORTANCE_DEFAULT);
    chan.setLightColor(Color.RED);
    chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
    NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    assert manager != null;
    manager.createNotificationChannel(chan);
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.