首页 文章

GCM推送通知的问题

提问于
浏览
3

关于StackOverflow的第一个问题,我将问一下Google Cloud Messaging服务,特别是Loopback的实现 .

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

因此,GCM启动背后的主要思想是检查设备是否已注册 .

这是通过简单检查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使我的应用程序的令牌无效 . 当服务器使用绑定到我的设备应用程序的令牌发送推送通知时,这会导致错误消息 .

类似的错误

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

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

正如谷歌文档所说,环回通过让服务器删除链接到有缺陷的RegistrationId的设备的记录来做出反应 . 可理解 .

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

设备应用程序不会处理新的注册 .

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

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


我发现了一个非常糟糕的解决方案

据我所知,在推送通知期间,唯一的错误信息从GCM返回到服务器,我在设备上做了一些小问题 .

这个想法很简单:使用我的服务器应该使用的头进行身份验证,向GCM服务器创建一个POST请求 . 这会导致错误被赋予设备本身,它可以解析JSON并注意发生了什么 . 从这里,该应用程序可以打造一个新的注册过程,解决问题 .

这有什么不好的?事实上,要将设备作为服务器进行身份验证,我必须对ServerKey进行硬编码并将其分发到每个应用程序中 . ServerKey应该只在服务器上使用,这使得这个解决方案成为一个非常糟糕的主意 .


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

在其他应用程序上,我've developed which use GCM just as well, I'已经以不同的方式解决了,例如让用户点击按钮或阅读服务器发送的一些特殊短信,然后首先启用GoogleCloudMessaging.unregister()并最终启用GoogleCloudMessaging.register()


那么,请求原谅这样的文本墙,你是如何解决这个NotRegistered的事情的?

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

1 回答

  • 1

    作为我评论的附录,因为它有所帮助,我在这里有更多空间:

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

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

    至于为什么令牌有时会发生变化,有时候不会:我不同意更多的是它是完全零星的,并且不禁感觉到我们并不知道有什么事情发生 .

    有时PACKAGE_REPLACED之后的新请求返回相同的密钥;有时它没有 . 在那些让它变得怪异的人之间会发生什么?上帝,我很乐意知道,我希望我有更多的信息 . 但这就是为什么我提到试图捕获广播的原因之一:强制检查何时发生应该确保你总是得到一个新的有效的(如果版本检查在不应该的情况下通过),如果它可用的话 .

    希望这有助于〜

相关问题