How do I update the notification text for a foreground service in Android?

AndroidServiceNotificationsForeground

Android Problem Overview


I have a foreground service setup in Android. I would like to update the notification text. I am creating the service as shown below.

How can I update the notification text that is setup within this foreground service? What is the best practise for updating the notification? Any sample code would be appreciated.

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);
		
	}

I am creating the service in my main activity as shown below:

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

Android Solutions


Solution 1 - Android

When you want to update a Notification set by startForeground(), simply build a new notication and then use NotificationManager to notify it.

The key point is to use the same notification id.

I didn't test the scenario of repeatedly calling startForeground() to update the Notification, but I think that using NotificationManager.notify would be better.

Updating the Notification will NOT remove the Service from the foreground status (this can be done only by calling stopForground );

Example:

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);
}

The documentation states

> To set up a notification so it can be updated, issue it with a > notification ID by calling NotificationManager.notify(). To update > this notification after you've issued it, update or create a > NotificationCompat.Builder object, build a Notification object from > it, and issue the Notification with the same ID you used previously. > If the previous notification is still visible, the system updates it > from the contents of the Notification object. If the previous > notification has been dismissed, a new notification is created > instead.

Solution 2 - Android

I would think that calling startForeground() again with the same unique ID and a Notification with the new information would work, though I have not tried this scenario.

Update: Based on the comments, you should use NotifcationManager to update the notification and your service continues to stay in the foreground mode. Take a look at the answer below.

Solution 3 - Android

Improving on Luca Manzo answer in android 8.0+ when updating the notification it will make sound and show as Heads-up.
to prevent that you need to add setOnlyAlertOnce(true)

so the code is:

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);
}

Solution 4 - Android

here's the code to do so in your service. Create a new notification, but ask notification manager to notify the same notification id you used in startForeground.

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

notificationManager.notify(ONGOING_NOTIFICATION, notify);

for full sample codes, you can check here:

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

Solution 5 - Android

It seems none of the existing answers show how to handle the full case - to startForeground if it's the first call but update the notification for subsequent calls.

You can use the following pattern to detect the right case:

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));
    }
}

Additionally you need to build the notification and channel as in other answers:

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);
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLukeView Question on Stackoverflow
Solution 1 - AndroidLuca ManzoView Answer on Stackoverflow
Solution 2 - AndroidCommonsWareView Answer on Stackoverflow
Solution 3 - AndroidhumazedView Answer on Stackoverflow
Solution 4 - AndroidDaniel KaoView Answer on Stackoverflow
Solution 5 - AndroidNick CardosoView Answer on Stackoverflow