向离线设备发送GCM通知

9
如果我向设备发送通知,但该设备处于离线状态,我会收到以下类似的消息:
错误:不可用
我必须重新发送。
我的问题是:
GCM服务器是否会将这些通知保留在队列中,并在设备上线时自动重新发送?还是完全由我处理?
因为如果GCM服务器将它们自动发送(一旦设备在线),直到它实际发送通知,我的服务器会认为它们已经发送。如何跟踪通知成功重新发送的时间?
我可以在服务器端通过查看“不可用错误消息”来标记未发送通知,但无法确定如何将其标记为已发送,一旦GCM成功发送通知。
谢谢
2个回答

11

根据文档 --- 当第三方服务器向GCM发布消息并收到消息ID时,并不意味着消息已经传递到设备。相反,它表示接受了该消息以便传递。消息被接受后会发生什么取决于许多因素。

如果设备已连接但处于空闲状态,则该消息将立即传递,除非将delay_while_idle标志设置为true。否则,它将存储在GCM服务器上,直到设备唤醒。这就是collapse_key标志起作用的地方:如果已经存在具有相同collapse key(和注册ID)的消息正在等待传递,则旧消息将被丢弃,新消息将取代其位置(即,新消息会折叠旧消息)。但是,如果未设置collapse key,则新旧消息都将存储以便日后传递。

注意:存储未折叠消息的数量有限制。该限制目前为100条。如果达到限制,则所有已存储的消息都将被丢弃。


我的服务器如何知道通知何时最终发送成功? - user1537779
我不相信从GCM服务器获取那些信息是可能的。这意味着你必须依赖于另一种通信方式,使客户端应用程序能够成功接收你的消息并与你的服务器进行通信。正如你所知道的,从GCM服务器得到的响应只会告诉你:成功:已处理的消息数量,没有错误。 或者失败:无法处理的消息数量。 - Kunal S. Kushwah
我可以在服务器端进行标记,通过查看“不可用”错误消息来确定通知是否已发送,但无法确定如何在GCM成功发送通知后将其标记为已发送。如果无法知道gcm服务器是否在以后某个时间发送了它们,则可能会再次发送相同的通知。 - user1537779
如果答案有帮助的话,标记一下并不会伤害你 :P - Kunal S. Kushwah
最初许多应用程序使用了GCM(包括WhatsApp),但后来它们转向了XMPP。Facebook转向了MQTT,而GTalk也实现了XMPP :) - Kunal S. Kushwah
显示剩余2条评论

2
我所做的是将“推送指示”与“有效载荷”分开。在我的GCM消息中,我只包括指向有效载荷的URI,并将有效载荷存储在数据库表中,通过消息中的URI可访问该表。
当客户端接收到消息时,它可能会看起来像这样,具有HATEOAS风格的链接:
{
  _links: {
    message: {
      rel: 'message',
      href: 'https://my-server.com/push/<messageId>'
    }
  }
}

客户端会通过URI获取消息负载,使用GET方法。此时服务器知道消息已被发送并可以相应地更新状态。获取负载还将删除它。
如果GCM重传不够健壮,这也意味着客户端可以选择手动获取所有待处理的消息,例如当网络连接在离线后恢复时,通过具有返回给定ANDROID_ID或类似标识符的所有消息的终端点来实现。如果稍后GCM消息确实被传递,客户端将在该消息中获得404的URI,并将其视为无操作,即消息已经处理完毕。
如果这样做过于复杂,轻量级的方法仅是为了实现服务器对消息传递的感知,可以创建一个终端点,仅确认接收到具有给定ID的消息,例如:
POST https://my-server.com/push/notifyReceived

{
  messageId: <messageId>
}

这是一个有趣的方法,但它并没有直接回答问题。GCM 会尝试重新投递吗? - Flimm
1
你说得对。这也许更适合作为评论,但有点长,我希望它能帮助某些人。 - JHH

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接