如何正确更新API 11及以上版本的通知文章?

18
  • 更新已在通知栏中的通知之前,Notification.Builder出现前,方法是调用setLatestEventInfo(),然后通过使用与第一个notify()调用匹配的ID,将通知传回NotificationManager.notify()

  • 现在 setLatestEventInfo()已弃用,并显示信息:请改用Notification.Builder。但我找不到任何有关如何使用Notification.Builder正确更新通知的文档。

  • 你只需要每次需要更新通知时重新创建新的Notification实例? 然后简单地将其传递给具有先前使用的ID的NotificationManager.notify()

  • 这似乎有效,但我想知道是否有任何官方验证说明这是新的“此方式”?

我询问的真正原因是因为在Android 4.1.1 Jelly Bean中,每次调用notify()时通知现在会闪烁。 当使用setProgress()更新进度条时,这看起来很糟糕,并且使得难以轻松点击通知。 在4.1或之前的版本中不是这种情况。 因此,在提交错误之前,我想确保自己做得正确。


你是从哪里更新通知的?我猜是一个服务吧..? - Ovidiu Latcu
你能否同时添加用于创建/更新通知的代码? - Ovidiu Latcu
4个回答

20

我通过在我的Notification.Builder上调用setWhen(0)解决了这个问题。似乎Android默认值不适合更新通知视图的一部分而不是整个通知淡入淡出。

Notification.Builder builder = new Notification.Builder(c)
                .setContentTitle("Notification Title")
                .setSmallIcon(R.drawable.ic_notification_icon)
                .setProgress(max_progress,current_progress,false)
                .setWhen(0);
                notification = builder.getNotification();

mNotificationManager.notify(NOTIFICATION_ID, notification);

更新:

WolframRittmeyer所述,使用when=0并不是一种优雅的方式。我创建了以下解决方案:

if(mNotif == null) {
//either setting mNotif first time
//or was lost when app went to background/low memory
    mNotif = createNewNotification();
}
else {
    long oldWhen = mNotif.when;
    mNotif = createNewNotification();
    mNotif.when = oldWhen;
}
mNotificationManager.notify(NOTIFICATION_ID, mNotif);

1
你应该使用 setWhen(Calendar.getInstance().getTimeInMillis()) 而不是 setWhen(0) - user1521536
2
@user1521536 为什么我们要这样做? - Patrick R.
谢谢。你的回答让我得到了正确的解决方案。但是,你应该为事件使用一个有意义的时间。如果更新使用相同的有意义的时间,通知将不会闪烁。只有当时间戳发生更改(如果没有明确设置when,则始终会发生更改),您的通知才会闪烁。请记住,when字段可能用于排序 - 现在或将来。将其设置为“0”可能会导致各种意想不到的麻烦。 - Wolfram Rittmeyer
@WolframRittmeyer 我认为我们可以通过这样做避免从系统获取时间(因为它只会产生闪烁效果):long oldWhen = mNotif.when; mNotif = createNewNotification(); mNotif.when = oldWhen; - Sufian
@sufian 嗯,mNotif 可能会超出范围(例如当用户滑动活动时)。这取决于你拥有什么。如果你有一个长时间运行的服务,这当然不是问题。但是,在我看来,每个通知都有一个自然的开始时间戳。例如,当用户开始播放一首歌曲时。或 GCM 消息的时间戳,或一天的开始时间,或进球的时间等等。如果你总是使用这个自然时间戳,一切都很好。 - Wolfram Rittmeyer
显示剩余3条评论

2
您所做的是正确的,只是您缺少可以设置的标志。我不知道您特定的通知实现,但可以考虑使用:
setOngoing(boolean ongoing)

或者

setOnlyAlertOnce(boolean onlyAlertOnce)

1
我猜测(因为我刚刚也遇到了同样的问题),你正在通知中使用RemoteView。我成功地更新了通知,使其不会像这样闪烁:
RemoteViews views;
if( this.mNotification == null) {
    views = new RemoteViews(getPackageName(), R.layout.notification);
    this.mNotification = new Notification.Builder(this)
        .setContent(views)
        .setSmallIcon(R.drawable.status_icon)
        .setContentIntent(mNotificationAction)
        .setOngoing(true)
        .setOnlyAlertOnce(true)
        .getNotification();
} else {
    views = this.mNotification.contentView;
}

感谢 @seanmonstar 回答 在通知栏中刷新进度条


你在使用startForeground()并在同一个通知上使用mNotificationManager.notify()后,是否成功解决了闪烁的问题? - Warlock

0

这里描述的解决方案很有效:悄悄更新正在进行中的通知

关键是要重用构建器并设置 setOnlyAlertOnce(true):

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

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