Android来电通知在应用从杀死状态唤醒后,后续通知的PendingIntent无法触发
兄弟,你这个问题我之前做视频通话SDK的时候也踩过坑!核心就是PendingIntent的复用机制在搞鬼——当应用从杀死状态被唤醒后,系统会缓存之前创建的PendingIntent实例,后续再发送相同规则的通知时,按钮点击就会因为复用了旧的PendingIntent而无法触发新的回调。我给你几个实测有效的解决办法:
一、给每个来电的PendingIntent设置唯一的requestCode
系统判断是否复用PendingIntent的关键指标之一就是requestCode。如果两次创建PendingIntent用了相同的requestCode,系统会直接返回之前的缓存实例,不会生成新的。所以你得给每个通话分配一个唯一的requestCode,比如用通话ID的哈希值、当前时间戳都可以:
// 假设callId是每个通话的唯一标识 val acceptRequestCode = callId.hashCode() val endRequestCode = callId.hashCode() + 1 // 给结束按钮也设个不同的编码 val acceptPendingIntent = PendingIntent.getActivity( context, acceptRequestCode, acceptIntent, // Android 12+必须加FLAG_IMMUTABLE,同时用FLAG_UPDATE_CURRENT确保Extra能更新 PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) val endPendingIntent = PendingIntent.getActivity( context, endRequestCode, endIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE )
二、给Intent添加唯一标识,避免系统判定为相同Intent
除了requestCode,系统还会对比Intent的内容(比如Action、Extra参数、Data字段)。哪怕requestCode相同,只要Intent的核心内容不一样,系统也会创建新的PendingIntent。所以给每个通话的Intent加个唯一的Extra参数,比如专属的通话ID:
val acceptIntent = Intent(context, CallAnswerActivity::class.java).apply { putExtra("UNIQUE_CALL_ID", callId) // 关键:每个通话的这个值都不重复 addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP) }
三、发送新通知前取消旧的来电通知
如果你的应用可能同时存在多个未处理的来电通知,建议在发送新通知前,先取消掉之前的所有来电通知,避免不同PendingIntent之间互相干扰:
val notificationManager = context.getSystemService(NotificationManager::class.java) // 可以用之前的通话ID作为通知ID,精准取消旧通知 notificationManager.cancel(previousCallNotificationId) // 再发送新的来电通知 notificationManager.notify(currentCallNotificationId, callNotification)
四、检查Activity的启动模式和Intent标记
确保处理来电的Activity没有设置过于严格的启动模式(比如singleInstance用错了会导致Activity无法重新创建)。推荐给Intent加上这两个标记:
FLAG_ACTIVITY_NEW_TASK:如果应用没在运行,会创建新的任务栈启动ActivityFLAG_ACTIVITY_CLEAR_TOP:如果Activity已经存在,会把它上面的所有Activity清除,直接带到栈顶
你可以先优先试试前两个办法,这俩是解决这类问题的核心。修改完后,先杀掉应用,发第一次通知唤醒应用,再发第二次通知测试按钮,应该就能正常触发PendingIntent了!
内容来源于stack exchange

