yeahman
yeahman

Reputation: 2767

multiple call to startforeground?

i have created a service (EmailService) that sends email ... each time i need to send an email with my app, it starts the service and pass the id of the email via an intent...

i am using startforeground(id_of_email, mynotifcation); to prevent it from being killed and to show a notification to the user of the status of the email sending.

i need to allow the user to send multiple emails at the time, so when the user needs to send another email, it again calls startservice with a new intent(different id of email)...so it calls startforeground(new_id_of_email, mynotifcation); again.

the problem is that the new call to startforeground overwrites the previous notification... (so the user loses the previous notification and doesn't know what is going on with his previous email)

Upvotes: 15

Views: 6550

Answers (3)

Pablo Espantoso
Pablo Espantoso

Reputation: 416

I created a utility class to manage foreground service notification(s) based on @zeekhuge's answer. You can find the snippet here: https://stackoverflow.com/a/62604739/4522359

Upvotes: 0

zeekhuge
zeekhuge

Reputation: 1594

One can also use STOP_FOREGROUND_DETACH flag.

Quoting from the documentation :

STOP_FOREGROUND_DETACH

added in API level 24 int STOP_FOREGROUND_DETACH Flag for stopForeground(int): if set, the notification previously provided to startForeground(int, Notification) will be detached from the service. Only makes sense when STOP_FOREGROUND_REMOVE is not set -- in this case, the notification will remain shown, but be completely detached from the service and so no longer changed except through direct calls to the notification manager.

Constant Value: 2 (0x00000002)

So, before a repeated call to startForeground() you can call stopForeground(STOP_FOREGROUND_DETACH);. This will detach the notification and repeated calls to startForeground() will not make modifications to it, if you use a different notification-id.

Further, the "detached" notification, now, does not represent the "ongoing service" and hence can be removed by user with a swipe.

BONUS :

For compatibility, one can use ServiceCompat class and its static method ServiceCompat.stopForeground(MyService.this, STOP_FOREGROUND_DETACH) as is documented here.

Upvotes: 2

Michael Powell
Michael Powell

Reputation: 766

Looking at the Service.startForeground() source shows that multiple calls to startForeground will only replace the currently shown notification. In fact, the call to startForeground is identical to stopForeground(), only with removeNotification set always set to true.

If you wish for you service to display a notification for each email in progress, you will have to manage each notification individually from the service.

public final void startForeground(int id, Notification notification) {
    try {
        mActivityManager.setServiceForeground(
                new ComponentName(this, mClassName), mToken, id,
                notification, true);
    } catch (RemoteException ex) {
    }
}

public final void stopForeground(boolean removeNotification) {
    try {
        mActivityManager.setServiceForeground(
                new ComponentName(this, mClassName), mToken, 0, 
                null, removeNotification);
    } catch (RemoteException ex) {
    }
}

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.3_r1/android/app/Service.java#Service.startForeground%28int%2Candroid.app.Notification%29

Upvotes: 7

Related Questions