如何在 Android 中更新前台服务的通知文本?

我有一个 Android 的前台服务设置。我想更新通知文本。我正在创建如下所示的服务。

如何更新在此前台服务中设置的通知文本?更新通知的最佳做法是什么?任何示例代码将不胜感激。

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);
77588 次浏览

我认为使用相同的惟一 ID 再次调用 startForeground()和使用新信息调用 Notification是可行的,尽管我还没有尝试过这种情况。

更新: 根据注释,您应该使用 NotifcationManager 更新通知,并且您的服务继续保持前台模式。看看下面的答案。

这是这样做的代码 为您服务。创建一个新的通知,但要求通知管理器通知您在 startForeground 中使用的相同通知 ID。

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

当您想要更新 startForeground ()设置的通知时,只需构建一个新的通知,然后使用 NotificationManager 通知它。

关键在于使用相同的通知 ID。

我没有测试重复调用 startForeground ()来更新 Notification 的场景,但是我认为使用 NotificationManager.tification 会更好。

更新通知不会从前台状态中删除服务(这只能通过调用 stopForground 来完成) ;

例如:

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()来更新通知 ID 发出、更新或创建 构建一个 Notification对象 它,并使用您以前使用的相同 ID 发出 Notification。 如果以前的通知仍然可见,系统将对其进行更新 从 Notification对象的内容 通知已被解除,则创建一个新通知 取而代之。

在安卓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);
}

现有的答案似乎都没有显示如何处理完整的情况-如果是第一个调用,则转到 startForeground,但是更新后续调用的通知。

您可以使用以下模式来检测正确的情况:

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