当应用程序处于后台并收到新电子邮件时,我会在通知栏中收到通知,如下所示:
Line 1 : Jane Smith Line 2 : Hi John,this is a sample message...
也就是说,特定于单个消息的通知,并且点击它会导致显示该特定电子邮件的屏幕.如果我通过滑动或“全部清除”来清除通知,那么当我收到新消息时,我将收到另一条消息特定通知.但是,如果我不清除它并且我收到另一封电子邮件,那么通知将变成摘要通知,说“2条新消息”,然后点击它会进入收件箱.
我知道如何更新通知,问题是如何确定通知栏中仍有哪些通知(如果有).答案并不那么简单,因为通知不会反映我有多少未读消息,它必须通过点击通知或清除通知来反映用户仍未确认哪些消息.
我应该通过保留我们发布的通知列表,被点击的通知(内容意图)和清除的通知(删除意图)来跟踪通知吗?我不认为这种方法是否足够安全……例如:如果因为我启动手机而通知被清除会怎样?我应该在哪里跟踪仍然显示的通知?共享偏好?
你通常如何解决这个问题?
解决方法
假设用户正在使用Gmail应用程序(忽略与浏览器版本的任何交互),然后导航离开它:
>从那时起,如果用户收到新电子邮件,它将收到通知.
>如果通知仍然存在且用户收到新电子邮件,则通知将更新为包含自用户上次使用该应用程序以来最近N封电子邮件标题的摘要.
>如果用户解除通知并且另一封电子邮件到达,则会发出另一个摘要通知.
>如果用户导航回应用程序(通过单击通知与否),则会解除所有现有通知.
在API 18中,Android添加了使用NotificationListenerService检索活动通知的支持,但是对于我正在使用的应用程序来说这是最近的(最小API 14),更不用说你不能依赖它来获取现有的通知信息,如果它已经被用户解雇了.
因此,我发现的解决方案是保留有关本地已发出的通知的信息,使用该信息创建单个通知或摘要,并在用户再次打开应用程序时清除所有内容.
public class NotificationBundle { private String mText; // Add any other relevant information about your notification here,// particularly what you used to create your notification intent // i.e. an item/message id to highlight,maybe? public String getText() { return mText; } public void setText(final String text) { mText = text; } }
我们的想法是为您发出的每个通知创建一个实例.
然后,您必须有一种方法来保留NotificationBundle对象列表.我使用SharedPreferences来做到这一点,但你可以使用其他更适合你的东西(比如DB表).要保留List< NotificationBundle>在SharedPreferences中我使用Gson将数组序列化为json,然后将其保存为字符串.假设您可以使用SharedPreferences,您可以在此answer中找到如何进行序列化.
有了这个结构,基本上你要做的就是:
>当您必须发出通知时:
>使用您要通知的信息创建新的NotificationBundle.
>检索现有的List< NotificationBundle>来自SharedPreferences
>如果您的捆绑包列表为空,您将发出单个通知.如果不是,您将发布摘要 – 在这种情况下,您可以使用捆绑包列表来构建摘要的内容.有关摘要通知的好文章是[使用大视图样式].
>将新的NotificationBundle(从1)添加到现有列表< NotificationBundle> (从2开始)并将其保存到SharedPreferences.
>使用NotificationManager.notify()发出通知.如果您始终在此处使用相同的通知ID,则会在您的应用中当前未显示任何通知时创建新通知,或者如果之前的通知可见,则会立即更新通知.
>在主Activity的onResume()方法中,确保使用NotificationManager.cancelAll()关闭所有通知.另外,请务必从您的SharedPreferences中删除现有的List< NotificationBundle>.
这应该可以解决问题.