FCM重复推送技术咨询:单次发送却收多条重复通知的原因及机制
针对你遇到的FCM重复推送问题,结合你提供的时间线(间隔2分钟、4分钟、8分钟的重复接收),我来逐一解答你的疑问:
一、重复推送的可能原因
- 设备端未发送送达确认(ACK):FCM服务器只有收到设备返回的ACK信号,才会标记推送成功。从你的时间线间隔来看,完全符合FCM的指数退避重试规律,说明每次推送后服务器都没收到ACK,所以反复重试发送。
- 设备状态或网络异常:如果设备在接收推送时处于弱网、休眠状态,或者系统临时出现异常,即便你的
MyPushListenerService收到了消息,系统层面的ACK可能没成功发送给FCM服务器。 - 数据消息处理异常:如果这是一条数据消息(而非通知消息),当你的
onMessageReceived方法执行超时、抛出未捕获异常时,FCM SDK不会自动发送ACK,服务器就会判定推送失败并触发重试。
二、Firebase确认推送送达的机制
- 对于通知消息:当系统FCM SDK收到推送后,会自动向FCM服务器发送ACK,无需开发者额外处理,服务器收到ACK后就会停止重试。
- 对于数据消息:需要你的
onMessageReceived方法正常执行完成(无超时、无未捕获异常),FCM SDK才会发送ACK。如果方法执行出现问题,ACK就不会被触发,服务器会认为消息未送达。
三、FCM的重试机制细节
- FCM内置了指数退避重试策略,也就是每次重试的间隔会按指数级增长(比如你看到的2分钟→4分钟→8分钟就是典型表现),目的是避免给服务器和设备造成过大压力。
- 重试触发的核心条件是:服务器未收到设备的ACK确认,或者推送过程中出现网络错误、设备离线等情况。
- 重试的次数和最大间隔由FCM服务器内部管控,开发者无法直接修改,但可以通过确保设备正常发送ACK来避免不必要的重试。
额外排查建议
你可以重点检查这几点:
- 你的
MyPushListenerService处理数据消息时有没有耗时操作、有没有未捕获的异常; - 设备在接收推送时段的网络状态是否稳定;
- 确认推送是通知消息还是数据消息,对应检查ACK的触发逻辑是否正常。
内容的提问来源于stack exchange,提问作者kyrax




