GCM 推送通知的问题

Issues with GCM Push Notifications

关于 Whosebug 的第一个问题,我将询问 Google 云消息服务,特别是 Loopback 的实施。

所以,我正在开发一个应用程序,并开始在不同的分支上工作,以介绍 Loopback 的推送通知处理和它的各种 REST 工具 Api。即使本主题将严格涵盖 Loopback 处理 GCM 的方式,该问题也与 Google 文档中描述的原始方式有关。

因此,GCM kick-off 背后的主要思想是检查设备是否已注册。

这是通过简单检查 SharedPreferences 变量来完成的,该变量是一个用于存储我们的 RegistrationID 值的名称。

final LocalInstallation installation = new LocalInstallation(context, adapter);

如果找到,设备必须通知服务器,传送令牌。 否则,必须向 GCM 注册。 完成后,设备会通知服务器。 ( registerInBackground(installation) 最终会在检索到 RegistrationId 后调用 saveInstallation(installation)

    if (installation.getDeviceToken() != null) {
        saveInstallation(installation);
    } else {
        registerInBackground(installation);
    }

如果通信成功,设备将使用 SharedPreferences 如上所述保存 RegistrationId。 (注意:getDeviceToken() 是 Loopback 通过 API SharedPreferences 中的值处理的方式)

假设每次创建我的 MainActivity 时都会执行此“GCM-Check”(因此,在 onCreate 方法期间)。

我们也知道 GCM 有时很乱,想要刷新我的应用程序的 RegistrationId 或其他一些东西,老实说,我现在还不是很清楚。简而言之,GCM 使我的应用程序的令牌无效。当服务器使用绑定到我的 device-app.

的令牌发送 push-notification 时,这会导致 error-message

类似于

的错误
{"multicast_id":0123456789012345678,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"NotRegistered"}]}

你可以看到,"failure":1"results":[{"error":"NotRegistered"}]

Loopback 的反应正如 Google 文档所说,通过让服务器删除链接到错误 RegistrationId 的设备的记录。 看得懂。

回到我们的设备。再次启动我的应用程序并加载 MainActivity,会导致相同的“GCM-check”过程。这次应用程序可以使用 SharedPreferences 找到 RegistrationId,并可以直接通知服务器,服务器根据给定的 RegistrationId 创建一条记录。

device-app没有处理新的注册。

你可以在这里看到循环。设备将不知道它的令牌无效,并将继续告诉服务器相同的数据,服务器将不断向错误的 registrationId 发送信息,从而在收到相关错误后将其删除。

问题在于应用程序必须依赖一次创建且永远不会被修改的数据。要删除旧数据,我应该向设备发送通知,这显然是不可能的,因为我无法从 GCM 访问它。其他可能的解决方案是通过发送电子邮件或短信通知用户,并要求他单击按钮,但我宁愿采用更“自动化”的方法来解决问题。


我找到了一个非常糟糕的解决方案

据我所知,只有 error-info 是在 push-notification 期间从 GCM 返回到服务器的,我对设备进行了一些修改。

想法很简单:创建一个 POST 请求到 GCM 服务器,使用 headers 我的服务器应该用来进行身份验证。这导致错误被提供给设备本身,它可以解析 JSON 并注意到发生了什么。应用程序可以从这里建立一个新的注册过程,解决这个问题。

这有什么不好? 事实上,要将设备验证为服务器,我必须 hard-code ServerKey 并将其分发到每个应用程序中。 ServerKey 应该只在服务器上使用,使这个解决方案成为一个非常糟糕的主意。


也就是说,使用 SharedPreference 值简单地让设备知道其状态的想法并不是很好,因为它只会告诉我是否至少注册过一次,而不会让我知道我的当前状态。

在我开发的其他也使用 GCM 的应用程序上,我用不同的方式解决了问题,比如让用户单击按钮或读取服务器发送的一些特殊短信,然后启用GoogleCloudMessaging.unregister() at first and eventually GoogleCloudMessaging.register()


所以,对于这样的wall-of-text请见谅,你是怎么解决这个NotRegistered的事情的?

感谢您的努力和时间阅读,希望您能回答:)

作为我评论的补充,因为它有帮助,我在这里有更多 space:

除了检查令牌是否存在于您的 SharedPreferences 中之外,您还应该检查令牌所针对的应用程序版本是否与当前 运行 检查的版本相匹配(即是 Google 文档的建议)。

如果设备版本不匹配,您应该请求一个有效的令牌(实际上可能相同,但不能保证)。现在,您可能还想检查 PACKAGE_REPLACED 广播(如果您每次安装测试时都没有增加清单中的版本,我对此感到非常内疚),如果被触发,应该还强制您请求新令牌。

至于为什么令牌有时会发生变化,有时却不会:我完全同意这完全是零星的,并且不禁觉得好像发生了一些我们并不真正了解的事情。

有时新的请求在PACKAGE_REPLACEDreturns相同的key之后;有时它没有。在使它变得奇怪的那些之间发生了什么?上帝,我很想知道,我希望我有更多关于它的信息。但这就是我提到尝试捕获该广播的部分原因:在它发生时强制进行检查应该确保您始终获得一个新的有效版本(如果版本检查在不应该通过的情况下通过)(如果它可用)。

希望对你有所帮助~