Android 旧通知被新通知无效
Android old notifications are invalid by a new one
我正在开发 Android 应用程序。它收到通知 A,如果用户单击通知,则显示内容(与 A 相关)。问题是:如果用户在收到多个通知时单击其中一个旧通知,它会显示与最新通知相关的内容,而不是它本身。比如我收到A、B、C、D(A是最新的)通知后,点击通知A显示内容A,点击B(或C或D)仍显示内容内容A.
我用来推送通知的代码如下:
Intent intent = new Intent(this, MainActivity.class);// start the main activity
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(MainActivity.EXTRA_TITLE, title);
intent.putExtra(MainActivity.EXTRA_URL, url);
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new Notification.Builder(this)
.setWhen(System.currentTimeMillis())
.setTicker(title)
.setContentTitle(title)
.setContentText(beacon.getDetail())
.setAutoCancel(true)
.setOngoing(false) // if it is true, the user cannot dismiss it
.setSmallIcon(R.drawable.ic_launcher)
.setOnlyAlertOnce(true)
.setDefaults(Notification.DEFAULT_ALL)
.setLights(0xff00ff00, 1000, 300)
.setSound(Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "6"))
.setVibrate(new long[] {
0, 100, 200, 300
})
//.addAction(0,"Cancel", dismissIntent)
//.addAction(0,"Open App", pi)
.build();
notification.contentIntent = pi;
notificationManager.notify(id, notification);
我不确定这是否是 Android 上的正常情况。如果不是,谁能帮我解决?如果是正常情况,谁能建议我实现上述要求的解决方案?提前谢谢你。
编辑:
十分感谢大家。在您的帮助下,我解决了问题。根据 PendingIntent doc,如果两个意图除了它们的 "extra" 之外是相同的,并且它们关联的待定意图也相同,那么 "two" 待定意图实际上只是一个待定意图,因为旧的pendingintent 在创建新的 pendingintent 时被重用。为了避免这种情况(实现我的要求),我需要通过修改它们的操作、数据、类型、class 和类别来确保两个意图不相同,或者确保两个 pendingintents 不相同通过修改他们的请求代码。就我而言,我选择了第二种解决方案:
PendingIntent pi = PendingIntent.getActivity(this, id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
我将通知的id分配给了它们对应的pendingintents的请求代码。尽管意图仍然是相同的(filterEquals),但是它们对应的未决意图是不同的,因为它们具有不同的请求代码。不同通知的id不一样,因为我要显示不同的内容
通过实验,它工作正常。
试试这个,它将取代旧的通知
notificationManager.notify(id, notification); <---make id the same integer for all notifications
It is important to know when two Intents are considered to be the same
for purposes of retrieving a PendingIntent. A common mistake people
make is to create multiple PendingIntent objects with Intents that
only vary in their "extra" contents, expecting to get a different
PendingIntent each time. This does not happen. The parts of the Intent
that are used for matching are the same ones defined by
Intent.filterEquals. If you use two Intent objects that are equivalent
as per Intent.filterEquals, then you will get the same PendingIntent
for both of them.
There are two typical ways to deal with this.
If you truly need multiple distinct PendingIntent objects active at
the same time (such as to use as two notifications that are both shown
at the same time), then you will need to ensure there is something
that is different about them to associate them with different
PendingIntents. This may be any of the Intent attributes considered by
Intent.filterEquals, or different request code integers supplied to
getActivity(Context, int, Intent, int), getActivities(Context, int,
Intent[], int), getBroadcast(Context, int, Intent, int), or
getService(Context, int, Intent, int).
我正在开发 Android 应用程序。它收到通知 A,如果用户单击通知,则显示内容(与 A 相关)。问题是:如果用户在收到多个通知时单击其中一个旧通知,它会显示与最新通知相关的内容,而不是它本身。比如我收到A、B、C、D(A是最新的)通知后,点击通知A显示内容A,点击B(或C或D)仍显示内容内容A.
我用来推送通知的代码如下:
Intent intent = new Intent(this, MainActivity.class);// start the main activity
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(MainActivity.EXTRA_TITLE, title);
intent.putExtra(MainActivity.EXTRA_URL, url);
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new Notification.Builder(this)
.setWhen(System.currentTimeMillis())
.setTicker(title)
.setContentTitle(title)
.setContentText(beacon.getDetail())
.setAutoCancel(true)
.setOngoing(false) // if it is true, the user cannot dismiss it
.setSmallIcon(R.drawable.ic_launcher)
.setOnlyAlertOnce(true)
.setDefaults(Notification.DEFAULT_ALL)
.setLights(0xff00ff00, 1000, 300)
.setSound(Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "6"))
.setVibrate(new long[] {
0, 100, 200, 300
})
//.addAction(0,"Cancel", dismissIntent)
//.addAction(0,"Open App", pi)
.build();
notification.contentIntent = pi;
notificationManager.notify(id, notification);
我不确定这是否是 Android 上的正常情况。如果不是,谁能帮我解决?如果是正常情况,谁能建议我实现上述要求的解决方案?提前谢谢你。
编辑: 十分感谢大家。在您的帮助下,我解决了问题。根据 PendingIntent doc,如果两个意图除了它们的 "extra" 之外是相同的,并且它们关联的待定意图也相同,那么 "two" 待定意图实际上只是一个待定意图,因为旧的pendingintent 在创建新的 pendingintent 时被重用。为了避免这种情况(实现我的要求),我需要通过修改它们的操作、数据、类型、class 和类别来确保两个意图不相同,或者确保两个 pendingintents 不相同通过修改他们的请求代码。就我而言,我选择了第二种解决方案:
PendingIntent pi = PendingIntent.getActivity(this, id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
我将通知的id分配给了它们对应的pendingintents的请求代码。尽管意图仍然是相同的(filterEquals),但是它们对应的未决意图是不同的,因为它们具有不同的请求代码。不同通知的id不一样,因为我要显示不同的内容
通过实验,它工作正常。
试试这个,它将取代旧的通知
notificationManager.notify(id, notification); <---make id the same integer for all notifications
It is important to know when two Intents are considered to be the same for purposes of retrieving a PendingIntent. A common mistake people make is to create multiple PendingIntent objects with Intents that only vary in their "extra" contents, expecting to get a different PendingIntent each time. This does not happen. The parts of the Intent that are used for matching are the same ones defined by Intent.filterEquals. If you use two Intent objects that are equivalent as per Intent.filterEquals, then you will get the same PendingIntent for both of them.
There are two typical ways to deal with this.
If you truly need multiple distinct PendingIntent objects active at the same time (such as to use as two notifications that are both shown at the same time), then you will need to ensure there is something that is different about them to associate them with different PendingIntents. This may be any of the Intent attributes considered by Intent.filterEquals, or different request code integers supplied to getActivity(Context, int, Intent, int), getActivities(Context, int, Intent[], int), getBroadcast(Context, int, Intent, int), or getService(Context, int, Intent, int).