为什么我通过Google云设备消息传递服务为我的设备获取多个有效令牌?

我刚刚添加了C2DMfunction到我的Android应用程序。

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

  1. 我的应用程序发送注册意向
  2. 答案广播是由我的应用程序接收
  3. 设备令牌从意图中检索并发送到我的服务器

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

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

  5. 用户重新安装应用程序

如果在步骤5之后发送推送通知,我的应用程序仍然收到此通知。 看起来,从以前的安装检索的令牌仍然是活动的,并重新连接到我的应用程序的新实例。

这有以下问题:

  • 重新安装我的应用程序但无意收到推送通知的用户不可能将自己从服务中删除,因为应用程序的新实例无法从我的服务器注销旧的令牌。

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

更新

我遵循了伯顿的build议,做了以下工作:

为了testing目的,每次启动应用程序时,都只需启动一个注销Intent。 发送注销意向后,我的服务器上的推送通知不会发送到我的应用程序。 这似乎是窍门,但如果我现在去C2DM设置屏幕,并打开我的应用程序的推送通知所有旧的令牌再次活跃,我收到的信息,我没有注册在我的应用程序的当前安装。

下次更新

看来我不是唯一有这个问题的人:

Android的C2DM:重复的消息到相同的设备和应用程序

我希望Google能够pipe理这些令牌,以便在发布新令牌之后,来自同一设备的旧令牌会被禁用。 我也希望在我发送一个unregister Intent之后,这个应用程序的所有标记都会被标记为无效或从Google Server中删除。 如果这是Google的特殊用例的devise决定,我不明白请赐教。

Solutions Collecting From Web of "为什么我通过Google云设备消息传递服务为我的设备获取多个有效令牌?"

我们现在find了一个解决scheme,应该在大多数情况下工作。

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

  • 如果消息中的令牌和存储在pref文件中的令牌相匹配,则设备现在仅显示通知。 这样,我们保证我们不会显示通过以前的安装获得的设备令牌的消息。
  • 如果令牌不匹配,我们发现一个旧的令牌不应该被激活了。 现在,我们将自己的Web服务器上的令牌标记为不活动,以防止服务器发送更多不必要的C2D消息

这个解决scheme使我们能够仅显示相关数据,而不需要存储唯一的用户ID。

在我的C2DM实现中,每个用户的设备令牌都保存在一个数据库中,与其UDID和应用程序的包名称(等等)保存在一起。 UDID和包名称形成主键,这意味着该表可以列出来自同一设备(UDID)的多个应用程序。 当用户运行一个特定的应用程序时,设备令牌被logging,如果他们卸载并重新运行应用程序,新的设备令牌将被logging在旧的。 我们也有列logging是否推动是特定的应用程序/设备组合,以及用户启用/禁用哪些types的推消息。

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

这个解决scheme应该可以解决你的问题,因为它阻止你发送推送到两个设备令牌。 我希望这有帮助!

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

更新
您可以通过使用collapse_key(或您自己创build的任何东西)作为标识符来区分不同的C2DM消息。 在注册之间进行更新,并在注册,注销和消息之后将其传递给设备。