更新正在进行的通知(静默方式)

53

我有一个连接到其他设备的无线服务。当启用服务时,我会有一个持续显示已启用状态的通知。

在启用服务后,用户连接到另一个设备。此时,我希望更新我的持续通知以显示已连接设备的名称。这很容易做到,只需再次调用 startForeground(ONGOING_NOTIFICATION,notification) 并带上更新的信息即可; 但是每次调用它都会在通知栏上闪烁通知。实际上,我希望通知能够在后台静默更新而不在通知栏上闪烁,这样用户在打开通知区域查看之前不会察觉到差别。

是否有一种方法可以更新通知而不调用 startForeground()

该行为仅出现在Honeycomb中。 Gingerbread设备(我认为Froyo等也是如此)的行为符合预期。

4个回答

80

我也遇到了这个问题,并且在参考之前的评论和一些研究后,找到了解决方法。

如果您不希望通知在更新时闪烁,或者持续占用设备状态栏,您必须:

  • 在构建器上使用setOnlyAlertOnce(true)
  • 对于每次更新,使用相同的构建器。

如果每次都使用新的构建器,那么我猜Android需要重新构建视图,导致它暂时消失。

以下是一些良好代码的示例:

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

通过上述代码,您只需要使用消息和进度(0-100)调用updateNotification(String, int),它将更新通知而不会打扰用户。


我不同意这个评估。 状态栏中显示的是滚动文本。从我的实验中可以得出结论,如果: 1.设置setOnlyAlertOnce(true)(我们在这方面达成一致) 2.未设置setTicker(CharSequence) 3.通知ID相同 那么就不会显示滚动条。 在我看来,每次更新都没有必要使用相同的构建器。 - Emanuel Moecklin
3
+1 表示指出了同一个构建器的重要性(文档中找不到)。 我自己尝试过:当通知抽屉关闭时没有区别。 但是,如果用户打开通知时发生更新,则通知会在短时间内消失,这会产生非常不愉快的闪烁。 使用相同的构建器可以神奇地解决此问题。(在4.1.2上进行了测试) - nevermind
谢谢,这个很好用。我使用 progress==0 是因为它更容易与我的实现一起使用。 - danny117
同一个构建者为我做了这个。 - Sam

34

根据文档,您应该更新现有的通知。


1
调用 notify() 时的行为与调用 startForeground() 相同。 - howettl
1
@howettl 你已经尝试过了吗?它可能会有不同的行为。如果这没有帮助,你可以尝试http://developer.android.com/reference/android/app/Notification.Builder.html#setOnlyAlertOnce(boolean)。 - denis.solonenko
17
在回复之前,我尝试了你的第一个建议。你的第二个建议让我找到了Notification类中的FLAG_ONLY_ALERT_ONCE标志,这导致了正确的行为。谢谢! - howettl
1
@howettl,可以分享一下你的代码吗?我也遇到了闪烁通知的问题,而且FLAG_ONLY_ALERT_ONCE无法正常工作。 - Martin Vandzura
3
如果调用setTicker(CharSequence),Android似乎会忽略FLAG_ONLY_ALERT_ONCE标志,因此如果你只想更新通知,请确保不设置滚动文本。 - Emanuel Moecklin

12

这对我起作用了,其中正在进行的活动(不是SERVICE)通知被“静默”更新。

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

2
谢谢,setOnlyAlertOnce(true)正是我需要的,它可以更改通知中的操作按钮,并且不会重新创建(隐藏/显示)新的通知。我已经在API中寻找了几个小时,没有意识到这个方法就是我需要的。 - Brad Martin

-4

试试这个

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

在notify()方法中使用此ID。您的Android系统时间会创建一个唯一的ID。


时间戳始终是唯一的。不能存在相同的时间戳。 - vishal-android-freak
你认为如果连续三次调用getTimeInMillis,你会得到三个不同的数字吗?毫秒是一个漫长的时间;你会看到很多很多重复的数字。 - James Moore
1
还要考虑到将毫秒级别的时代截断为整数大小肯定不会是唯一的,如果持续通知几天,就会出现这种情况。如果您想要一个唯一的ID(虽然与原始问题无关),那么最好从SharedPreferences中检索一个整数,并在检索时递增它。 - Yeti

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