将通知固定在通知区域的顶部

12

我有一个通知,每三秒钟就会刷新(即发送)。我已经设置了FLAG_ONGOING_EVENT标志和FLAG_NO_CLEAR标志,以便它始终显示。问题是,如果例如下载是活动的(在通知区域中显示进度条),由于它们都每隔几秒钟进行刷新,因此两个通知不断交换位置。

如何将我的通知固定在列表顶部(或某个静态位置),以便每次调用NotificationManager.notify()更新时,它都不会再跳来跳去?

编辑:这是更新通知的代码。它每三秒运行一次。

Notification notification = new Notification();
notification.contentView = appBarNotification; // this sets the changed notification content
notification.flags |= Notification.FLAG_ONGOING_EVENT;  
notification.flags |= Notification.FLAG_NO_CLEAR; 

Intent notificationIntent = new Intent();
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.contentIntent = contentIntent;
notification.icon = R.drawable.icon;

nm.notify(APP_BAR_NOTIFICATION, notification);

你每次调用 notify() 时使用相同的 ID 吗? - Gyan aka Gary Buyn
是的,这就是我所做的。我会在问题中发布相应的代码。 - ubuntudroid
8个回答

20

有一种解决方案可以完全满足你的需求。

Notification类中,有一个名为when的公共字段。根据API:

通知的时间戳。图标和扩展视图按此键排序。

默认行为(包括代码和编码人员 :))是将时间戳分配给when来表示通知的时间戳:

notification.when = System.currentTimeMillis();
所以,为了保持通知的正确顺序,您只需要给它一个预设的时间戳:
notification.when = previousTimestamp;

当您对所有通知执行此操作时,它们将保持其顺序。我曾经和您一样遇到了同样的问题,并通过这种方式解决了它。


嗯,所以你正在一遍又一遍地创建关于过去发生事件的新通知。这很聪明。不过,我认为对于大多数其他情况来说,单个持续事件通知会是更好的解决方案。 - Ed Burnette
mmmm 是 Long 类型... 你可以将其转换为 int,但在版本 > 5.0中总是有效,2012 可以工作,但在 2015 中却不起作用!! 抱歉已废弃。 - user3402040
我很高兴找到了解决我问题的方法。但是...不幸的是,我无法理解如此简单的答案:(。我就是没明白重点在哪里... previousTimestamp - 它来自哪里?它是给上一个更新的通知赋予的时间戳,还是同一通知的先前更新时间,或者是什么?有人能澄清一下吗? - Liphtier
@Liphtier - 原始通知的时间戳。只要您使用相同的时间戳,通知就会保留在队列中的位置。 - Vaiden
@Vaiden - 我尝试了这个方法但没有成功,而且似乎这个解决方案已经过时了。至少在API >=21的情况下,通知“when”值默认为开始时间,因此手动设置相同的值没有任何效果。它不会影响通知顺序。然而,我发现设置高优先级是导致通知跳跃播放的原因,它们覆盖了每个通知的优先级。 - Liphtier

5

您不应该一直发送通知。只需使用正在进行的事件标志,就像您已经在代码中使用的那样。其他通知可能会出现并遮盖您的通知,但这就是Android的工作方式。


我必须每隔几秒钟重新发送通知,因为它是一份当前正在运行的应用程序列表,需要更新。我只想将列表放在一个固定的位置(不一定是最顶部),这样用户就不必每次想使用它时都要搜索它。 - ubuntudroid
嗯,似乎在Android中没有办法实现所需的行为。因此,这个答案似乎是最合适的。 - ubuntudroid
实际上有一个解决方案,至少对我有效。请在此页面底部查看我的答案。 - Vaiden

3
你是每次发送新通知还是更新现有的通知?可以发一下代码吗?
同时,你可以通过思考“如果两个或更多程序都试图将它们的通知固定在列表的第一位置,会发生什么?”来回答类似“我可以将我的通知固定到静态位置或列表顶部”这样的问题,并意识到由于程序之间的军备竞赛,它们会不断努力确保自己的通知排名靠前,这种特性因此不支持。

Nik是正确的 - 如果每个开发者都可以让他们的应用程序在其他所有应用程序之上显示通知,那么为什么不呢? - Snailer
一个静态位置就足够了,它不必在列表的最顶部 - 只要尽可能高即可。 - ubuntudroid
我不知道如何在不使用相同的ID重新发送通知的情况下“更新”现有通知,因此这就是我每三秒钟要做的事情...我将在问题中发布代码。 - ubuntudroid
但是,如果你不想成为第一名,只是想要一个静态的位置,那么一个不会“抢占第一名”的解决方案是可行的(也是问题的答案)。因此,“如果发生了什么”问题的答案是:他们将在列表中获得一个随机(但静态)的位置。 - Nanne
是的,一个静态位置完全足够。 - ubuntudroid
这将是我首选的答案。作为一名狂热的Android用户,我不希望应用程序窃取通知,无论是在第一位还是其他位置。我会重新考虑您的应用逻辑,因为如果我想知道哪些应用程序正在运行或应用程序提供的任何其他功能,我会打开该应用程序。您可以在通知栏上创建一个图标,就像许多人所做的那样(Skype等)。您不需要每3秒钟发送一次通知来打扰用户。这很烦人。祝你好运! - davidcesarino

1

我已经有一段时间没有为Android编写代码了,但如果我记得正确的话,每当您调用NotificationManager.notify()时,都是因为您希望通过移动或闪烁图标来提醒用户。但是,有一些修改您正在发送的实际通知的方法。

如果需要,您还可以在其上调用.cancel()

这里是Android API文档以供参考,尽管您可能已经看过它们:

Notification

NotificationManager

希望这有所帮助!


抱歉,我没有找到有关“更新”正在运行的通知的任何信息。重新发送(即调用notify())并附上新内容是我所知道的唯一方法... - ubuntudroid

1

正如您所看到的,我已经在我的代码中使用了FLAG_ONGOING_EVENT。问题是,例如下载进度条也使用它,因此两者每隔几秒钟就会在进行中的区域切换位置。尽管如此,您可能对FLAG_NO_CLEAR标志是正确的 - 我必须测试一下,尽管它不会解决我的主要问题。 - ubuntudroid
FLAG_ONGOING_EVENT仅用于指示Android不要解除通知。它与排序无关。 - Vaiden

1
你说你的通知显示当前正在运行的应用程序列表。为什么要每 3 秒重新发送一次通知呢?为什么不仅在应用程序列表更改时重新发送通知。这并不能直接解决您的问题,但可以显著减少问题发生的频率。

你说得完全正确 - 我已经实现了这样一个功能,但目前它没有按预期工作。因此,我暂时切换回了3分钟的解决方案。然而,正如你所说,这并不能真正解决我的一般性问题... - ubuntudroid

1

这应该是正确的答案,因为其他的已经过时了。 - lasec0203

-1

对于遇到这个问题的其他人,我想提醒一下 -

Vaiden的答案解决了我的持续通知跳动的问题。这只发生在我们的应用程序上ICS 4.0.3上,我认为这是因为ICS从旧版本中不同地处理通知。还要注意的是 - 在平板电脑上,与旧版本(Gingerbread)不同,没有“正在进行”和普通通知部分。但顺序仍然保持,只是没有分类。不确定它是否适用于ICS上的手机。


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