通知通过旧的Intent Extras


134

我正在通过以下代码在BroadcastReceiver中创建一个通知:

String ns = Context.NOTIFICATION_SERVICE;
        NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(ns);
        int icon = R.drawable.ic_stat_notification;
        CharSequence tickerText = "New Notification";
        long when = System.currentTimeMillis();

        Notification notification = new Notification(icon, tickerText, when);
        notification.defaults |= Notification.DEFAULT_VIBRATE;
        long[] vibrate = {0,100,200,200,200,200};
        notification.vibrate = vibrate;
        notification.flags |= Notification.FLAG_AUTO_CANCEL;

        CharSequence contentTitle = "Title";
        CharSequence contentText = "Text";
        Intent notificationIntent = new Intent(context, NotificationActivity.class);
        notificationIntent.putExtra(Global.INTENT_EXTRA_FOO_ID, foo_id);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);

        notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);

        int mynotification_id = 1;

        mNotificationManager.notify(mynotification_id, notification);

当我单击通知时,它将打开NotificationActivity,并且在Activity中可以从Intent-Bundle中检索foo_id(例如1)

但是,如果触发了另一个通知并再次单击它,则该活动仍会从Intent-Bundle中接收到“旧”值(1)。我试图用clear()清除捆绑包,但是收到了同样的效果。我认为我的代码有误。


请告诉我如何从待定意图中获取数据
user49557

意识到它正在发送旧的临时演员,使我的分诊更加容易。
Utsav Gupta

Answers:


268

您正在为您的待处理强度发送相同的请求代码。更改此:

PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);

至:

PendingIntent contentIntent = PendingIntent.getActivity(context, UNIQUE_INT_PER_CALL, notificationIntent, 0);

如果发送相同的参数,则不会创建意图。它们被重用。


1
所以UNIQUE_INT_PER_CALL是我必须提供的整数?还是这是在某个地方声明的静态变量?
BrianM 2011年

23
android gotcha#147-因此Intent,具有不同附加功能的(via putExtra)被视为相同并被重复使用,因为我没有为某些未决的意图调用提供唯一的
沃尔玛

你知道吗,我很粗心。我只是想如何在一个块中保持0(在我的情况下):(
Exigente05

3
这对我来说是非常有用的,对其他人来说只是个提示,很可能您是用相同的方法构建通知的,因此您可以将新的待处理意图的ID设置为与您要使用的ID相同用于通知的唯一ID!
詹姆斯·麦克尼

1
@IncrediApp,与PendingIntent.getBroadcast()相同;?
Shruti

139

另外,您可以使用以下代码生成PendingIntent:

PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

从文档中获取PendingIntent.FLAG_UPDATE_CURRENT

如果描述的PendingIntent已经存在,则保留它,但用此新Intent中的内容替换其额外数据。如果您在仅更改附加项的情况下创建意图,并且不关心接收到先前PendingIntent的任何实体将能够与您的新附加项一起启动它,即使没有明确为其指定它们,也可以使用此方法。


谢谢...正在为添加“ PendingIntent.FLAG_UPDATE_CURRENT”这个标志而努力:)
Najib Ahmed Puthawala

1
为我工作,使用挂起的意图将状态从设置警报转移到广播接收器。
William T. Mallard'Mar

我只是希望我在将通知发送给用户之前知道这些标志的实际作用(!)高兴地解决了我的麻烦……
James Andrew

42

您正在传递相同的ID。在这种情况下,请从以下时间开始创建唯一的ID:

int iUniqueId = (int) (System.currentTimeMillis() & 0xfffffff);

并这样写:

PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(),iUniqueId, intentForNotification, 0);

3
为什么不使用new Random()。nextInt()
演示

@hderanga将“&0xfffffff”添加到上面的int会做什么?
AJW

3
@AJW System.currentTimeMillis()返回long,而requestIdof 的参数为PendingIntent.getActivity()int。0xffffffff是一个位掩码。尽管还有更多内容,但简单的解释是,执行“ long&0xffffffff”会给出long中最低的32位,并丢弃最高的32位,从而使您实质上具有32位int。这比简单地转换为int更好,因为它不会破坏符号位(如果将大于int的long转换为int,则符号位将溢出,并且可能以负值结束)
约旦·邦多

8

对于长时间寻找最佳方法的任何人,您都需要传递PendingIntent.FLAG_UPDATE_CURRENT作为最后一个参数,如下所示

PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

您甚至不需要提供新的唯一ID。

您需要下次再做一次,而不是第一次


1
那行不通,我来到这里是因为那就是我在做什么。
Brill Pappin

您不需要下次执行此操作,这将是第一次。
温柔的

0

您所有通知的请求代码均为0。更改以下行:

PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);

带有:

PendingIntent contentIntent = PendingIntent.getActivity(context, new Random().nextInt(), notificationIntent, 0);

1
使用“ new Random()。nextInt()”而不是“ System.currentTimeMillis()”有什么好处吗?
AJW

使用random可以很容易地在意外情况下再次重新生成相同的整数值,从而导致很难发现已传递旧意图的错误。
山姆

@AJW在我的情况下。我在同一毫秒内创建了2个不同的通知,因此其中一个收到了错误的附加信息。
艺人

0

只是想添加另一个选项

 PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.