我有一个前台服务通知,点击后应该开始一项活动。这个活动在调用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);
工作得很好......
我使用了Android开发者网站上的标准通知代码,并使用“通知”构建器对其进行了测试。无论如何我得到相同的结果。除非Activity调用finish();
,否则它完美地工作这是预期的行为,是一个错误,还是我错过了什么?
我提前感谢您的帮助,希望能找到解决方案!
注意:我使用的通知代码是完全标准的,所以我没有发布它。 RandomActivity调用finish();在onCreate,所以也没有什么不寻常的。
答案 0 :(得分:12)
在尽我所能尝试之后,我终于找到了解决方案。如果有人遇到这个问题,也会发布。
我必须将int requestCode与通知ID匹配。为什么?绝对不知道......我只能假设它会阻止意图数据变为空或重用它?
private static int ONGOING_NOTIFICATION_ID = 76;
PendingIntent contentIntent = PendingIntent.getActivity(this,
ONGOING_NOTIFICATION_ID, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
与startForeground的通知ID相同:
this.startForeground(ONGOING_NOTIFICATION_ID, not);
希望这有助于某人。
答案 1 :(得分:4)
我不需要检查通知ID(与您的建议一样),但我必须将标记更改为FLAG_UPDATE_CURRENT
,而不是FLAG_ONE_SHOT
。
使用FLAG_ONE_SHOT
,待处理的意图一旦传递就会被取消,之后,没有任何数量的通知将允许再次传递相同的待处理意图,因此例外。
这对我来说是个问题。
答案 2 :(得分:0)
我刚刚遇到了类似的问题,它不是前台通知,但是有时单击通知会导致Sending contentIntent failed: android.app.PendingIntent$CanceledException
错误,但没有任何反应。所以我只想描述我的问题和解决方案,因为我在这里寻找它。
对我来说,问题是我在服务器上有一个剩余的安装对象,因此实际上我得到了两次FCM onMessageReceived事件,并两次发布了本地通知。因为它与同一事件相关,所以它被实现为替换自身,因此我没有注意到。
但是我正在使用当前时间生成具有10ms精度的唯一requestCode,因此,如果第二个调用在第一次调用后的10ms内发布了本地通知,则它将获得相同的请求代码。
我还使用了标志FLAG_CANCEL_CURRENT,但是它应该只取消先前的挂起意图并创建一个新的意图。
所以,然后我尝试将requestCode设为常量-仍然,有时意图很好。
我认为罪魁祸首是这两个调用并发运行,有时,取消了其未完成的通知的通知实际上是在以后发布,代替了具有正在执行的未完成的通知。
我的解决方案: 我确保onMessageReceived中的代码等待上一个调用完成。它停止发生,一切正常。我还在onMessageReceived方法内部添加了一些过滤功能,以忽略传入的推送,这些推送具有完全相同的数据,并且间隔不到5秒就被接收到。
答案 3 :(得分:0)
我的问题源于多个PendingIntent
相等;在这种情况下,取消一个PendingIntent
会取消所有“重复项”。
Per the Android documentation:
重要的是要知道何时两个Intent被认为是相同的,以便检索PendingIntent。人们经常犯的一个错误是创建多个PendingIntent对象,它们的Intent仅在其“额外”内容中有所不同,期望每次都获得一个不同的PendingIntent。这不会发生。用于匹配的Intent部分与Intent#filterEquals(Intent)定义的部分相同。如果您使用与Intent#filterEquals(Intent)等效的两个Intent对象,则它们将获得相同的PendingIntent。
关于如何处理此问题的两个建议:
如果您确实确实需要同时激活多个不同的PendingIntent对象(例如,用作同时显示的两个通知),那么您将需要确保存在一些不同的内容< / strong>,将其与其他PendingIntent相关联。 这可能是Intent#filterEquals(Intent)考虑的任何Intent属性,或提供给getActivity(Context,int,Intent,int),getActivities(Context,int,Intent [ ],int),getBroadcast(Context,int,Intent,int)或getService(Context,int,Intent,int)。
如果一次只需要一个PendingIntent来激活要使用的任何Intent,则可以选择使用标志FLAG_CANCEL_CURRENT或FLAG_UPDATE_CURRENT来取消或修改与您提供的Intent相关的任何当前PendingIntent。 / p>
它们的动作,数据,类型,标识,类和类别相同。这不会比较意图中包含的任何其他数据。请注意,从技术上讲,当实际与IntentFilter进行匹配时,标识符将被忽略,而在这里它会像其他字段一样直接进行相等性比较。