Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to correctly handle startForegrounds two notifications

I have an IntentService that uploads a file. Everything works fine, but I'm a little confused about how to handle the notifications. When I start the notification I use startForeground() because the files can be rather large and I don't want the upload to get killed unless absolutely necessary. When I use startForeground() it displays two notifications in the notification area (one under Ongoing and one under Notifications):

Example:

I've read through a number of different Stack Overflow posts and web articles, but none of them answer the question I have...hopefully I haven't missed one that talks about ths.

It's my understanding that the ongoing notification in the image above (the one without the progress bar) is put there since this is running in the foreground (Services documentation). That's all well and good if you ask me, and I understand why. However, I don't need two notifications displayed and I'm pretty sure most people wouldn't want two notifications cluttering up the notification area either. I would like to know how to properly handle the notification so that only one displays and doesn't clutter up the notification area.

The only way I've been able to get around this is if I set the integer ID for startForeground (int id, Notification notification) (ONGOING_NOTIFICATION_ID in my code below) to zero. However, the documentation I quote above says:

Caution: The integer ID you give to startForeground() must not be 0

Setting it to 0 disables the Ongoing notification and then just shows the regular notification with the progress bar. I figure I could kind of "fix" this by setting .setOngoing(true) until it's done uploading the file and then setting .setOngoing(false) once it's finished, so it can be dismissed. I'm not sure exactly how "Cautious" one has to be with setting the integer ID to 0. To me it kind of seems like a lazy way to be able to get around the issue I'm having, but I don't know if there are other consequences for setting it to 0. Also, this only works if I only have one notification that I'm dealing with. If I have multiple, different notifications, then I'll need different IDs for each one and this won't work. Update: It looks like setting the ID to 0 won't work in Android 4.3, so now I'm back to square one.

What is a valid way to get around displaying both notifications?

Update/Solution: Duh, taking some time off and then coming back to this and double-checking what I had done based on @dsandler 's recommendation helped me figure out what I was doing wrong. I wasn't setting the correct ID when I was doing the progress update, so that's why it was creating two notifications and one wasn't getting updated. Using the same ID (ONGOING_NOTIFICATION_ID) for all the notifications solved the issue for me. See the code below for the additional pieces I hadn't included before and where I had made the mistake.

Relevant code from UploadFile.java:

public class UploadFile extends IntentService {

    private static final int ONGOING_NOTIFICATION_ID = 1;

    @Override
    protected void onHandleIntent(Intent intent) {
        mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mBuilder = new NotificationCompat.Builder(this);
        mBuilder.setContentTitle(getText(R.string.upload))
            .setContentText("0% " + getText(R.string.upload_in_progress))
            .setSmallIcon(android.R.drawable.stat_sys_upload);

        startForeground(ONGOING_NOTIFICATION_ID, mBuilder.build());


....

    if (progress > 0){
        percent = (Long.valueOf(progress) * 100) / totalSize;
        mBuilder.setProgress(100, percent.intValue(), false);
        mBuilder.setContentText(percent.intValue() + "% " + getText(R.string.upload_in_progress));
        mNotifyManager.notify(ONGOING_NOTIFICATION_ID, mBuilder.build()); // <-- My problem was that I had set the ID here to 0 and did not make it the same as the ID I set above
    }                       

....

}
like image 542
Jason Avatar asked Aug 03 '13 05:08

Jason


People also ask

How do you handle multiple notifications?

Set the unique id to let Notification Manager knows this is a another notification instead of same notification. If you use the same unique Id for each notification, the Notification Manager will assume that is same notification and would replace the previous notification.

How to stop foreground notification Android?

In your implementation, use the same foreground id you used for your main foreground service. The parameter (true) in the stopForeground method call indicates that the notification should be removed. Now, we just have to start this dummy service in the service we want to run in the foreground without notification.

What are foreground notifications?

Foreground services show a status bar notification, so that users are actively aware that your app is performing a task in the foreground and is consuming system resources. Devices that run Android 12 (API level 31) or higher provide a streamlined experience for short-running foreground services.


1 Answers

First off, judging by your description, you might be able to get away with a regular service, recognizing that the out-of-memory killer won't come calling unless things are getting dire on the device and your service has really been running a very long time.

That said, if you must make the service foreground, the typical strategy here is to show your progress using the Notification you used when you put your service into the foreground state. Using NotificationManager.notify you can post as many updates to that notification as you like, including adjustments to progress bars via Notification.Builder.setProgress, for example.

In this way you only show one notification to the user, and it's the one required by startForeground.

like image 121
dsandler Avatar answered Sep 18 '22 06:09

dsandler