通知pendingIntent contentIntent在活动调用finish()时失败



我有一个前台服务通知,当单击它时,应该会启动一个活动。在调用finish()之前,此活动的寿命非常短。

第一次点击通知时,它工作了,第二次,然后我得到了错误:

Sending contentIntent failed: android.app.PendingIntent$CanceledException

在创建前台服务通知的代码中,我将randomActivity.class更改为另一个不调用finish的Activity类,它在每次单击时都能完美工作。发件人:

Intent notificationIntent = new Intent(this, RandomActivity.class);

至:

Intent notificationIntent = new Intent(this, HomeActivity.class);

工作正常。。。

我使用了安卓开发者网站上的标准通知代码,并使用Notificationbuilder进行了测试。不管怎样,我都得到了同样的结果。除非Activity调用finish();

这是预期行为、错误还是我遗漏了什么

我提前感谢你的帮助,希望能找到解决方案!

注意:我使用的通知代码是完全标准的,所以我还没有发布。RandomActivity调用finish();在onCreate中,所以在那里也没有什么异常。

在尽我所能之后,我终于找到了解决方案。发布以防有人也遇到这个问题。

我必须将int requestCode与通知id进行匹配。为什么?绝对不知道。。。我只能假设它可以防止意向数据变为空或重复使用它?

private static int ONGOING_NOTIFICATION_ID = 76;
PendingIntent contentIntent = PendingIntent.getActivity(this,
ONGOING_NOTIFICATION_ID, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

与启动Foreground:的通知id相同

this.startForeground(ONGOING_NOTIFICATION_ID, not);

希望这能帮助到别人。

我不需要检查通知id(就像您建议的那样),但我必须将标志更改为FLAG_UPDATE_CURRENT,而不是FLAG_ONE_SHOT

对于FLAG_ONE_SHOT,一旦交付,挂起的意图就会被取消,在此之后,再多的点击通知也不允许再次交付相同的挂起意图,因此是例外。

这就是我的问题。

我刚刚遇到了一个类似的问题,它不是前台通知,但有时单击通知会导致Sending contentIntent failed: android.app.PendingIntent$CanceledException错误,但什么也没发生。所以我只想描述我的问题和解决方案,因为我在这里寻找它。

对我来说,问题是我在服务器上有一个剩余的安装对象,所以我实际上得到了两次FCM onMessageReceived事件,并发布了两次本地通知。它是为了取代自己而实现的,因为它与同一事件有关,所以我没有注意到。

但我使用当前时间生成一个唯一的requestCode,精度为10ms,所以如果第二个调用在第一个调用后10ms内发布了本地通知,它会得到相同的请求代码。

我也使用了flag_CANCEL_CURRENT标志,但它应该只是取消之前挂起的意图并创建一个新的意图。

所以,然后我试图使requestCode成为一个常量——尽管如此,有时目的还是很好的。

我认为罪魁祸首是这两个调用并行运行,有时,取消pendingIntent的通知实际上是后来发布的,取代了正在工作的pendingIntnt。

我的解决方案:我确保onMessageReceived中的代码等待上一次调用完成。它停止了,一切都很好。我还在onMessageReceived方法中添加了一些过滤,以忽略传入的推送,这些推送具有完全相同的数据,并且在不到5秒的时间内收到。

我的问题源于多个PendingIntent相等;在这种情况下,取消一个PendingIntent将取消所有"重复项"。

根据Android文档:

为了检索PendingIntent,了解两个Intent何时被视为相同非常重要。人们常犯的一个错误是使用Intents创建多个PendingIntent对象,这些对象的"额外"内容各不相同,期望每次都得到不同的PendingIntent。这种情况不会发生。Intent中用于匹配的部分与Intent#filterEquals(Intent)定义的部分相同。如果根据Intent#filterEquals(Intent)使用两个等效的Intent对象,那么您将为这两个对象获得相同的PendingIntent。

关于如何处理此问题的两个建议:

如果您确实需要同时激活多个不同的PendingIntent对象(例如用作同时显示的两个通知),则您需要确保它们有不同之处,以便将它们与不同的Pending Intent相关联这可以是Intent#filterEquals(Intent)考虑的任何Intent属性,也可以是提供给getActivity(Context,int,Intent,int)、getActivities(Context,int,Intent[],int),getBroadcast(Context,intt,Intent)或getService(Context,int,Intent、int)的不同请求代码整数

如果您将要使用的任何Intent一次只需要激活一个PendingIntent,那么您也可以使用标志FLAG_CANCEL_CURRENT或FLAG_UPDATE_CURRENT来取消或修改与您提供的Intent关联的任何当前PendingIntent。

当:时,两个意图相等

它们的操作、数据、类型、标识、类和类别是相同的。这不会比较意图中包含的任何额外数据。请注意,从技术上讲,当实际与IntentFilter匹配时,会忽略标识符,而在这里,它与其他字段一样直接进行相等性比较。

最新更新