Android 通知未以 FIFO 方式处理
Android notifications not handled in a FIFO way
我正在使用 NotificationManager to send notifications via a NotificationChannel。
我用同一个通知ID发送多条(40+)条通知,向用户展示操作的进度。我希望每个通知都会覆盖最后一个通知。
有时(尤其是在有 40 多个进度更新的情况下)通知似乎没有按照我发送它们的顺序处理,这导致我的“最终”成功通知丢失的问题最后一个通知是未完成的进度通知之一。
我确认我的代码以预期的顺序发送通知,但我很困惑,因为我在 NotificationManager
或 NotificationChannel
的文档中没有找到任何指示顺序(如果有的话) ) 通知已处理。
我知道我可以通过为最终成功通知使用不同的 ID 来解决我的主要问题,但这仍然可能会导致向用户显示的进度有时会倒退...
我错过了什么吗?文档是否说明了处理通知的顺序?
好的,在玩了一个重现问题的最小项目后,我弄清楚了发生了什么。
Android 上有通知限制以防止 DOS 攻击(有道理)。 This article 很好地解释了这一点。限制可能是 50 个通知(每个包),但这取决于设备。我的测试设备限制为 25 条通知。我仍然无法在文档中找到任何相关信息。
不幸的是,这篇文章中的解决方案在我的特定情况下不起作用,因为当我在 NotificationCompat.Builder
上使用 setProgress()
时,我仍然只有一个活动通知。但该解决方案可能适用于有大量活动通知在较长时间内堆积起来的情况。
更令人失望的是:我最初的解决方法(参见问题)的想法也不起作用,因为如果独立于通知 ID 达到限制,通知仍将被删除。
有问题的代码在NotificationManagerService
:
// Limit the number of toasts that any given package except the android
// package can enqueue. Prevents DOS attacks and deals with leaks.
if (!isSystemToast) {
int count = 0;
final int N = mToastQueue.size();
for (int i=0; i<N; i++) {
final ToastRecord r = mToastQueue.get(i);
if (r.pkg.equals(pkg)) {
count++;
if (count >= MAX_PACKAGE_NOTIFICATIONS) {
Slog.e(TAG, "Package has already posted " + count
+ " toasts. Not showing more. Package=" + pkg);
return;
}
}
}
}
mToastQueue
是一个 ArrayList,所以基本上通知是以 FIFO 方式处理的,但是如果队列已满,将丢弃较新的通知,然后处理队列中较旧的通知,这是是什么让我觉得顺序错乱了。
TL;DR
如果您快速发送通知(尤其是在使用进度更新时),则有丢失其中许多通知的风险。
我想我会停止使用确定的进度通知,只在开始时发送一个不确定的通知。或者在超时后发送重要的最后一个并接受进度更新可能会关闭。
我正在使用 NotificationManager to send notifications via a NotificationChannel。
我用同一个通知ID发送多条(40+)条通知,向用户展示操作的进度。我希望每个通知都会覆盖最后一个通知。
有时(尤其是在有 40 多个进度更新的情况下)通知似乎没有按照我发送它们的顺序处理,这导致我的“最终”成功通知丢失的问题最后一个通知是未完成的进度通知之一。
我确认我的代码以预期的顺序发送通知,但我很困惑,因为我在 NotificationManager
或 NotificationChannel
的文档中没有找到任何指示顺序(如果有的话) ) 通知已处理。
我知道我可以通过为最终成功通知使用不同的 ID 来解决我的主要问题,但这仍然可能会导致向用户显示的进度有时会倒退...
我错过了什么吗?文档是否说明了处理通知的顺序?
好的,在玩了一个重现问题的最小项目后,我弄清楚了发生了什么。
Android 上有通知限制以防止 DOS 攻击(有道理)。 This article 很好地解释了这一点。限制可能是 50 个通知(每个包),但这取决于设备。我的测试设备限制为 25 条通知。我仍然无法在文档中找到任何相关信息。
不幸的是,这篇文章中的解决方案在我的特定情况下不起作用,因为当我在 NotificationCompat.Builder
上使用 setProgress()
时,我仍然只有一个活动通知。但该解决方案可能适用于有大量活动通知在较长时间内堆积起来的情况。
更令人失望的是:我最初的解决方法(参见问题)的想法也不起作用,因为如果独立于通知 ID 达到限制,通知仍将被删除。
有问题的代码在NotificationManagerService
:
// Limit the number of toasts that any given package except the android
// package can enqueue. Prevents DOS attacks and deals with leaks.
if (!isSystemToast) {
int count = 0;
final int N = mToastQueue.size();
for (int i=0; i<N; i++) {
final ToastRecord r = mToastQueue.get(i);
if (r.pkg.equals(pkg)) {
count++;
if (count >= MAX_PACKAGE_NOTIFICATIONS) {
Slog.e(TAG, "Package has already posted " + count
+ " toasts. Not showing more. Package=" + pkg);
return;
}
}
}
}
mToastQueue
是一个 ArrayList,所以基本上通知是以 FIFO 方式处理的,但是如果队列已满,将丢弃较新的通知,然后处理队列中较旧的通知,这是是什么让我觉得顺序错乱了。
TL;DR 如果您快速发送通知(尤其是在使用进度更新时),则有丢失其中许多通知的风险。
我想我会停止使用确定的进度通知,只在开始时发送一个不确定的通知。或者在超时后发送重要的最后一个并接受进度更新可能会关闭。