更新通知的文本,而不是整个通知。

66

前言

我正在尝试在通知栏中添加一个计时器,这个计时器是一个服务。每秒钟会调用一次下面这行代码(continueThread是一个表示是否运行中的布尔值,timeString是显示时间的字符串):

NotificationChrono.updateNotification(getApplicationContext(), continueThread, 
NOTIF_ID, timeString, "Chronometer", notificationManager);

这是 NotificationChrono 类:

public class NotificationChrono {

    static public void updateNotification(Context context, boolean running,
        int id, String title, String text,
        NotificationManager notificationManager) {

        Intent stopIntent = new Intent("com.corsalini.david.barcalc.STOP");
        PendingIntent stopPendingIntent = PendingIntent.getBroadcast(context,
            0, stopIntent, 0);

    Intent startIntent = new Intent(
            "com.corsalini.david.barcalc.STARTPAUSE");
    PendingIntent startPendingIntent = PendingIntent.getBroadcast(context,
            0, startIntent, 0);

    NotificationCompat.Builder builder = new NotificationCompat.Builder(
            context)

            .setContentText(context.getString(R.string.notif_text))

            .setContentTitle(title)

            .setSmallIcon(R.drawable.ic_action_alarm_2)

            .setAutoCancel(false)

            .setOngoing(running)

            .setOnlyAlertOnce(true)

            .setContentIntent(
                    PendingIntent.getActivity(context, 10, new Intent(
                            context, FrontActivity.class)
                            .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP), 0))
            .addAction(
                    running ? R.drawable.ic_action_pause
                            : R.drawable.ic_action_play,
                    running ? context.getString(R.string.pause) : context
                            .getString(R.string.start), startPendingIntent)
            .addAction(R.drawable.ic_action_stop,
                    context.getString(R.string.stop), stopPendingIntent);

    notificationManager.notify(id, builder.build());
}
}

问题

每秒钟通知都被删除并重新创建,视觉上意味着每秒钟通知会在通知列表中消失并重新出现。

我希望只更新标题文本,而不是每秒重新创建整个通知。这可能吗?


如果我的答案为您解决了问题,请将其接受为答案 :) - PieterAelse
我没有使用你的答案,实际上我不太记得我当时具体是怎么做的(我想关键在于 setWhen)。但是看了你的答案,似乎是更好的解决方案,我会接受它! - David Corsalini
3个回答

137

一定要每次使用同一个NotificationCompat.Builder生成器来创建Notification

第一次需要设置所有内容,但在第二次使用Builder时,只需设置您想要更新的值。之后,就像您之前做的那样,调用notificationManager.notify(id, builder.build())即可。如果使用相同的ID,则通知会被更新(非常重要!)。

例如:

//First time
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
            .setContentText(context.getString(R.string.notif_text))
            .setContentTitle(title)
            .setSmallIcon(R.drawable.ic_action_alarm_2)
            .setAutoCancel(false)
            .setOngoing(running)
            .setOnlyAlertOnce(true)
            .setContentIntent(
                    PendingIntent.getActivity(context, 10, 
                            new Intent(context, FrontActivity.class)                                 
                            .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP),
                    0)
            )
            .addAction(running ? R.drawable.ic_action_pause 
                               : R.drawable.ic_action_play,
                       running ? context.getString(R.string.pause)
                               : context.getString(R.string.start),
                       startPendingIntent)
            .addAction(R.drawable.ic_action_stop, context.getString(R.string.stop),
                    stopPendingIntent);

notificationManager.notify(id, builder.build());

//Second time
builder.setContentTitle(title);
notificationManager.notify(id, builder.build());

但是您也可以使用NotificationCompat类的setUsesChronometer方法。这将自动显示一个计时器,使用给定的时间戳(可以使用setWhen进行设置)。


1
通知管理器(notificationManager)来自哪里? - Rena
3
在Android中,您可以通过以下方式获取NotificationManager: 在Java中:NotificationManager notificationManager = getSystemService(NotificationManager.class); 在Kotlin中: val notificationManager: NotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - PieterAelse
这样,在一些更新之后,它会显示“包已经发布或排队了XXX个通知。不再显示更多。”但是我总是想要更新...所以这不可能吗? - Perry
1
第二次使用Builder时,您只需要设置要更新的值即可。每次都设置所有内容,否则在系统更新通知时,未设置的内容将会丢失。您还可能会遇到“IllegalArgumentException: Invalid notification (no valid small icon)”错误。已在Android 11上进行了测试。 - Osagui Aghedo
对于那些想知道如何在Java中获取通知管理器的人 -> notificationManager = NotificationManagerCompat.from(context); - Osagui Aghedo
请确保每次创建通知时都使用相同的NotificationCompat.Builder!这是错误的!只要使用与原始通知相同的通知ID和频道ID,您可以自由地使用新的NotificationCompat.Builder实例进行更新。 - Cyber Avater

8

您需要将通知标记为“仅提示一次”

Builder#setOnlyAlertOnce(true)

5

感谢PieterAelse的想法!

在我的情况下,第二次及之后我不得不采用这种方式(构建新通知):

        builder.setContentText(getConvertedTime(millisUntilFinished));
        Notification notification = builder.getNotification();
        notification.flags = Notification.FLAG_ONGOING_EVENT;            
        nm.notify(R.string.app_name,notification);

希望这有所帮助。

1
感谢提到ONGOING_EVENT标志,我也在寻找它。 - CybeX
这可能对一些人有用(通知优先级)- https://dev59.com/pWcs5IYBdhLWcg3wjUqR#35106689 - CybeX

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接