53

I have a service which connects to other devices wirelessly. When the service is enabled, I have an ongoing notification which states it is enabled.

After the service is enabled, the user then connects to another device. At this point, I would like to update my ongoing notification to state the name of the device which has been connected to. This is easy enough to do by calling startForeground(ONGOING_NOTIFICATION, notification) again with the updated information; however this flashes the notification on the bar each time it is called. What I would really like is the notification to quietly update in the background without flashing on the notification bar so the user doesn't know the difference until he or she opens the notification area to look.

Is there someway to update the notification without calling startForeground()?

This behavior only occurs in Honeycomb. Gingerbread devices (and I assume Froyo, etc.) behave the desired way.

howettl
  • 12,419
  • 13
  • 56
  • 91

4 Answers4

80

I too experienced this issue, and with help of previous comments and a bit of digging I have found the solution.

If you do not want notifications to flash when updated, or to continuously hog the status bar of the device,you must:

  • Use setOnlyAlertOnce(true) on the builder
  • Use the SAME Builder for each update.

If you use a new builder each time, then I am guessing Android has to rebuild the view all over again causing it to briefly disappear.

An example of some good code:

class NotificationExample extends Activity {

  private NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
  private mNotificationManager =
    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

  //Different Id's will show up as different notifications
  private int mNotificationId = 1;    

  //Some things we only have to set the first time.
  private boolean firstTime = true;

  private updateNotification(String message, int progress) {
    if (firstTime) {
      mBuilder.setSmallIcon(R.drawable.icon)
      .setContentTitle("My Notification")
      .setOnlyAlertOnce(true);
      firstTime = false;
    }
    mBuilder.setContentText(message)
    .setProgress(100, progress, true);

    mNotificationManager.notify(mNotificationId, mBuilder.build());
  }
}

With the above code, you can just call updateNotification(String, int) with a message and progress (0-100) and it will update the notification without annoying the user.

Chris Noldus
  • 2,432
  • 2
  • 20
  • 27
  • I don't agree with this assessment. What is showing in the status bar is the ticker text. From my experiments I can conclude that the ticker isn't shown if: 1. setOnlyAlertOnce(true) is set (we agree on this one) 2. setTicker(CharSequence) is NOT set 3. the notification id is identical IMO there's no need to use the same builder for each update. – Emanuel Moecklin Dec 23 '13 at 00:17
  • 3
    +1 for pointing that the same builder is important (couldn't find that in documentation). Just tried it myself: when notification drawer is closed there is no difference. However, if an update occurs while notifications are opened by user, the notification disappears for a few moments, which produces quite unpleasant blinking. Using the same builder magically solves this problem. (Tested on 4.1.2) – nevermind Sep 07 '14 at 15:56
  • Thanks this worked nicely. I used progress==0 because it was easier to do with my implimentation. – danny117 Oct 28 '14 at 20:30
  • same builder did it for me – Sam Jun 24 '15 at 16:54
34

You should update existing notification as per the docs.

user16217248
  • 3,119
  • 19
  • 19
  • 37
denis.solonenko
  • 11,645
  • 2
  • 28
  • 23
  • 1
    The behavior when calling `notify()` is the same as if I had called `startForeground()`. – howettl Jun 20 '11 at 06:00
  • 1
    @howettl have you already tried that? It might behave differently.. If that doesn't help you could try http://developer.android.com/reference/android/app/Notification.Builder.html#setOnlyAlertOnce(boolean) – denis.solonenko Jun 20 '11 at 06:02
  • 17
    I did try your first suggestion before replying. Your second suggestion led me to the FLAG_ONLY_ALERT_ONCE flag in the Notification class, which resulted in the correct behavior. Thanks! – howettl Jun 20 '11 at 06:30
  • 1
    @howettl Can you share your code? I have same problem with flashing notification and FLAG_ONLY_ALERT_ONCE doesn't work – Martin Vandzura Feb 07 '13 at 14:21
  • 3
    If setTicker(CharSequence) is called Android seems to ignore the FLAG_ONLY_ALERT_ONCE flag, so make sure the ticker text is NOT set if you just want to update the notification. – Emanuel Moecklin Dec 23 '13 at 00:18
12

This worked for me, whereby an ongoing activity (not SERVICE) notification is updated 'silently'.

NotificationManager notifManager; // notifManager IS GLOBAL
note = new NotificationCompat.Builder(this)
    .setContentTitle(YOUR_TITLE)
    .setSmallIcon(R.drawable.yourImageHere);

note.setOnlyAlertOnce(true);
note.setOngoing(true);
note.setWhen( System.currentTimeMillis() );

note.setContentText(YOUR_MESSAGE);

Notification notification = note.build();
notifManager.notify(THE_ID_TO_UPDATE, notification );
Britc
  • 623
  • 5
  • 8
  • 2
    Thanks, `setOnlyAlertOnce(true)` was exactly what I needed to change the action buttons in the notification and it not recreate (hide/show) a new notification. Been looking through the API for hours and didn't realize that method was what I needed. – Brad Martin Jul 12 '18 at 06:00
-4

Try this

    int id = (int) Calendar.getInstance().getTimeInMillis();

Use this id in the notify() method. Time of your Android System itself creates a unique ID

  • Timestamps are always unique. There cannot be same time stamp. – vishal-android-freak Nov 01 '16 at 18:29
  • You think that if you call getTimeInMillis three times in a row, you're going to get three different numbers? A millisecond is a _long_ time; you're going to see many, many duplicates. – James Moore Nov 02 '16 at 03:12
  • 1
    Also consider that truncating an epoch in milliseconds to integer size will definitely not be unique with a persistent notification that lasts for days. If you wanted a unique ID (although not relevant to the original question), then it's better to retrieve an integer from SharedPreferences and increment it upon retrieval. – Yeti Jul 21 '19 at 13:31