为什么我的设备使用Google Cloud To Device Messaging Service获得多个活动令牌?

时间:2011-08-08 15:33:57

标签: android android-c2dm

我刚刚将C2DM功能添加到我的Android应用中。

如果在我的应用程序中启动C2DM,则会发生以下情况。

  1. 我的应用程序发送注册意图
  2. 我的应用
  3. 收到了答复广播
  4. 从意图中检索设备令牌并将其发送到我的服务器

    从那一刻起,一切正常。客户端收到推送通知等。 如果以下情况出现问题:

  5. 用户在不禁用推送的情况下卸载应用程序。 (完全删除它不仅更新)

  6. 用户重新安装应用程序
  7. 如果在步骤5之后发送推送通知,我的应用仍会收到此通知。 似乎从先前安装中检索到的令牌仍处于活动状态,并重新连接到我的应用程序的新实例。

    这导致了以下问题:

    • 重新安装我的应用但无意接收推送通知的用户无法从服务中删除自己,因为该应用的新实例无法从我的服务器取消注册旧令牌。

    这是C2DM系统中的错误还是我的设置有问题?

    更新

    我遵循了Berdons的建议并做了以下事情:

    出于测试目的,每次我的应用启动时才启动取消注册Intent。 发送取消注册后,我的服务器的推送通知不会发送到我的应用程序。这似乎可以解决问题,但如果我现在进入C2DM设置屏幕并打开我的应用程序的推送通知,所有旧令牌将再次激活,并且我会收到我当前安装的应用程序中未注册的信息。< / p>

    下次更新

    似乎我不是唯一有这个问题的人:

    Android C2DM : Duplicate message to the same device and App

    我希望Google能够管理这些令牌,使得同一设备的旧令牌在发布新令牌后被禁用。我还希望在我向该应用程序发送取消注册Intent所有令牌后,该设备被标记为无效或从Google服务器中永久删除。如果这是某种特殊用例的谷歌设计决定,我看不到请赐教。

3 个答案:

答案 0 :(得分:4)

我们现在找到了一个适用于大多数情况的解决方案。

服务器将C2DM注册ID添加为每个C2D消息的数据字段。

  • 如果消息中的令牌与pref文件中存储的令牌匹配,设备现在仅显示通知。这样我们就可以保证不显示以前安装获得的设备令牌的消息。
  • 如果令牌不匹配,我们发现了一个不再有效的旧令牌。我们现在将我们自己的Web服务器上的令牌标记为非活动状态,以防止服务器发送更多不必要的C2D消息

此解决方案使我们只显示相关数据,而无需存储唯一的用户ID。

答案 1 :(得分:3)

在我的C2DM实现中,每个用户的设备令牌都会根据其UDID和应用程序的包名称(以及其他内容)保存在数据库中。 UDID和包名称构成主键,这意味着该表可以列出来自同一设备(UDID)的多个应用程序。当用户运行特定应用程序时,将记录设备令牌,如果他们卸载并重新运行应用程序,则新设备令牌将记录在旧设备上。我们还有一些列来记录针对特定应用/设备组合的推送是否有效,以及用户启用/禁用了哪些类型的推送消息。

当需要为特定应用程序发送推送时,不会多次注册UDID(因为这两个字段构成主键),因此将仅使用最新的设备令牌。此外,我们的查询仅返回已启用推送消息的行。

此解决方案应解决您的问题,因为它会阻止您将推送发送到两个设备令牌。我希望这有帮助!

答案 2 :(得分:1)

更像是一个意想不到的“功能”。您可以考虑在应用程序的“首次运行”(首次运行)上发出取消注册请求,以防止发生这种情况。

<强>更新
您可以通过使用collapse_key(或您自己创建的任何内容)作为标识符来区分不同的C2DM消息。在注册之间更新它,并在注册,取消注册和消息后将其传递给设备。