这确实是由Google Cloud Messaging 中不切实际的心跳间隔造成的。
这可能是 GCM 中最令人沮丧的错误。GCM 的工作原理是维护从 Android 设备到 Google 服务器的空闲套接字连接。这很棒,因为它几乎不消耗电池电量(与轮询相反),并且它允许在消息到达时立即唤醒设备。为确保连接保持活动状态,Android 将在移动连接上每 28 分钟发送一次心跳,在 WiFi 上每 15 分钟发送一次。如果心跳失败,则连接已终止,GCM 将重新建立它并尝试检索任何未决的推送通知。心跳间隔越高,消耗的电池越少,设备从睡眠中唤醒的次数就越少。
然而,这是有代价的:心跳间隔越长,识别断开的套接字连接所需的时间就越长。在部署 GCM 之前,谷歌没有在现实生活中对这些间隔进行足够彻底的测试。这些间隔的问题是由网络路由器和移动运营商引起的,他们在几分钟不活动后断开空闲套接字连接。通常,这在廉价的家用路由器中更为常见,其制造商决定了空闲套接字连接的最长寿命,并终止它以节省资源。这些路由器只能处理有限数量的并发连接,因此采取这种措施是为了防止过载。这会导致 GCM 套接字终止,并且当传递 GCM 消息时,它不会到达设备。设备只会在发送心跳的时间(0 到 28 分钟后)才意识到连接已断开,这会在某些情况下(例如,当消息对时间要求严格时)使推送通知变得无用。根据我的经验,大多数便宜的路由器会在大约 5 到 10 分钟不活动后终止空闲连接。
我写了一篇关于这个和其他 GCM 问题的完整文章:
http://eladnava.com/google-cloud-messaging-extremely-unreliable/
谷歌云消息传递的替代方案
Pushy ( https://pushy.me/ ) 是一个独立的推送通知网关,完全独立于 GCM。它维护自己的后台套接字连接,就像 GCM 一样,以接收推送通知。底层协议是 MQTT,一种极其轻量级的发布/订阅协议,占用的网络带宽和电池非常少。
Pushy 的一个巨大优势在于,用于发送推送通知(从服务器)和注册设备以获取推送通知的代码实际上在 GCM 和 Pushy 之间是可互换的。这使得在实施 GCM 之后切换到 Pushy 变得非常容易,并且因为它的不稳定性而不得不放弃它。
(全面披露:我为自己的项目创建了 Pushy,并意识到许多应用程序将从这样的服务中受益)