简体   繁体   English

GCM推送通知的问题

[英]Issues with GCM Push Notifications

for my first question on StackOverflow I'm gonna ask about Google Cloud Messaging service, and in particular Loopback's implementation. 关于StackOverflow的第一个问题,我将问一下Google Cloud Messaging服务,特别是Loopback的实现。

So, I'm developing an app and started to work on a different branch to introduce Loopback's push notification handling and it's various tools for REST Api. 所以,我正在开发一个应用程序,并开始在不同的分支上工作,介绍Loopback的推送通知处理,以及REST Api的各种工具。 Even if this topic is gonna cover strictly Loopback's way to handle GCM, the question is also related to the original way as is described on Google docs. 即使这个主题将严格涵盖Loopback处理GCM的方式,但问题也与Google文档中描述的原始方式有关。

So, the main idea behind GCM's kick-off is to check whether the device is registered or not. 因此,GCM启动背后的主要思想是检查设备是否已注册。

This is done by a simple check on a SharedPreferences variable, a name used to store our RegistrationID value. 这是通过简单检查SharedPreferences变量来完成的,该变量是用于存储我们的RegistrationID值的名称。

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

If this is found, the device has to notify the server, communicating the token. 如果找到,则设备必须通知服务器,并传送令牌。 Else, a registration to GCM has to be done. 否则,必须完成GCM的注册。 Once this is done, the device notifies the server. 完成此操作后,设备会通知服务器。 ( registerInBackground(installation) will eventually call saveInstallation(installation) after retrieving RegistrationId ) registerInBackground(installation)最终会在检索RegistrationId后调用saveInstallation(installation)

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

If communication is successful, the device saves RegistrationId using SharedPreferences as described above. 如果通信成功,设备将使用SharedPreferences保存RegistrationId,如上所述。 (NOTE : getDeviceToken() is Loopback's way to handle via API the value in SharedPreferences) (注意:getDeviceToken()是Loopback通过API处理SharedPreferences中的值的方法)

Let's say this "GCM-Check" is being done every time my MainActivity is being created (so, during the onCreate method). 假设每次创建MainActivity时都会执行“GCM-Check”(因此,在onCreate方法期间)。

We also know GCM is sometimes messy, and wants to refresh my app's RegistrationId or some other stuff that, to be honest, is not completely clear to me right now. 我们也知道GCM有时候很乱,并想刷新我的应用程序的RegistrationId或其他一些东西,说实话,我现在还不完全清楚。 In short terms, GCM invalidates the token of my app. 简而言之,GCM使我的应用程序的令牌无效。 This causes an error-message when the server send a push-notification using the Token bound to my device-app. 当服务器使用绑定到我的设备应用程序的令牌发送推送通知时,这会导致错误消息。

An error similar to 类似的错误

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

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

Loopback reacts just as Google docs say, by having the server remove the record of the device linked to the faulty RegistrationId . 正如谷歌文档所说,环回通过让服务器删除链接到有缺陷的RegistrationId的设备的记录来做出反应。 Comprehensible. 可理解。

Back to our device. 回到我们的设备。 Launching my app again and loading MainActivity, causes the same "GCM-check" procedure. 再次启动我的应用程序并加载MainActivity会导致相同的“GCM检查”过程。 This time the app can find RegistrationId using SharedPreferences, and can directly notify the server, which creates a record with the given RegistrationId. 这次app可以使用SharedPreferences找到RegistrationId,并且可以直接通知服务器,服务器使用给定的RegistrationId创建记录。

No new registration is being handled by the device-app. 设备应用程序不会处理新的注册。

You can see the loop in here. 你可以在这里看到循环。 Device will have no knowledge of it's token invalidity and will continue to tell the server the same data, which will keep sending information to the wrong registrationId, thus removing it after receiving the related error. 设备将不知道它的令牌无效,并将继续告诉服务器相同的数据,这将继续向错误的registrationId发送信息,从而在收到相关错误后将其删除。

The problem is that the app has to rely on data which is created once and never gets modified. 问题是应用程序必须依赖于一次创建但永远不会被修改的数据。 To remove the old data I should send a notification to the device, which is obviously not possible as I can't reach it from GCM. 要删除旧数据,我应该向设备发送通知,这显然是不可能的,因为我无法从GCM到达它。 Other solutions possible is notify the user by sending an email or sms, and ask him to click a button for example, but I'd rather have a more "automated" approach to the problem. 其他可能的解决方案是通过发送电子邮件或短信通知用户,并要求他点击按钮,但我宁愿采用更“自动化”的方法解决问题。


A VERY BAD SOLUTION I'VE FOUND 我找到了一个非常糟糕的解决方案

As to my knowledge the only error-info is returned from GCM to the server during a push-notification, I've made a little hack on the device. 据我所知,在推送通知期间,唯一的错误信息是从GCM返回给服务器的,我在设备上做了一些小问题。

The idea is simple: create a POST request to GCM Servers, using the headers my server should use to authenticate. 这个想法很简单:使用我的服务器用来进行身份验证的标头,向GCM服务器创建一个POST请求。 This causes the error to be given to the device itself, which can parse the JSON and notice what happened. 这会导致错误被赋予设备本身,它可以解析JSON并注意发生了什么。 From here the app can forge a new registration process, fixing the issue. 从这里,该应用程序可以打造一个新的注册过程,解决问题。

What is bad about this? 这有什么不好的? The fact that to authenticate the device as the server, I have to hard-code the ServerKey and distribute it in every app. 事实上,要将设备作为服务器进行身份验证,我必须对ServerKey进行硬编码并将其分发到每个应用程序中。 The ServerKey should be used only on the server, making this solution a very bad idea. ServerKey应该只在服务器上使用,这使得这个解决方案成为一个非常糟糕的主意。


This being said, the idea of simply letting the device know its state using a SharedPreference value is not so great, as it would only tell me if I ever registered at least once, without letting me know my current status. 这就是说,简单地让设备使用SharedPreference值知道其状态的想法并不是那么好,因为它只会告诉我是否至少注册过一次,而不让我知道我的当前状态。

On other apps I've developed which use GCM just as well, I've solved in different ways, like having a Button to be clicked by the user or reading some specials SMS send by the server, which then enable GoogleCloudMessaging.unregister() at first and eventually GoogleCloudMessaging.register() 在我开发的其他使用GCM的应用程序中,我已经用不同的方式解决了,例如让用户点击按钮或阅读服务器发送的一些特殊短信,然后启用GoogleCloudMessaging.unregister()起初,最后是GoogleCloudMessaging.register()


So, asking for forgiveness for such a wall-of-text, how have you solved this NotRegistered thing? 所以,请求原谅这样的文本墙,你是如何解决这个NotRegistered的事情的?

Thanks for your effort and time in reading and, hopefully, in answering : ) 感谢您的努力和阅读时间,并希望在回答:)

As an addendum to my comments, since it helped and I have more space here: 作为我评论的附录,因为它有所帮助,我在这里有更多空间:

Instead of just checking whether or not the token exists inside your SharedPreferences, you should also check to see if the version of your app that token is for matches the version that is currently running the check (that was a suggestion from Google's docs). 除了检查令牌是否存在于您的SharedPreferences中之外,您还应该检查您的应用程序的那个令牌的版本是否与当前运行检查的版本相匹配(这是来自Google文档的建议)。

If the device version do not match, you should request a valid token (which could actually be the same, but is not guaranteed). 如果设备版本不匹配,您应该请求一个有效的令牌(实际上可能是相同的,但不能保证)。 Now, you may also want to check for the PACKAGE_REPLACED broadcast (in case you're not incrementing the version in your manifest each time you install for tests, which I'm very guilty of) which, if triggered, should also force you to request a new token. 现在,您可能还想检查PACKAGE_REPLACED广播(如果您在每次安装测试时没有增加清单中的版本,我非常内疚),如果触发,也应该强制您请求新令牌。

As for why there's sometimes a change in the token and sometimes not: I couldn't agree more that it's totally sporadic and can't help feeling like there's something going on we don't really know about. 至于为什么有时令牌会发生变化而有时候却没有:我完全同意它是完全零星的,并且不禁感觉到我们并不知道有什么事情发生。

Sometimes the new request after PACKAGE_REPLACED returns the same key; 有时PACKAGE_REPLACED之后的新请求返回相同的密钥; sometimes it doesn't. 有时它没有。 What happens in between those that makes it weird? 在那些让它变得怪异的人之间会发生什么? God, I would LOVE to know, and I wish I had more info on it. 上帝,我很乐意知道,我希望我有更多信息。 But that's part of why I mentioned trying to catch that broadcast: forcing the check when it happens should ensure that you're always getting a new valid one (in the event that the version check passes when it shouldn't) if it's available. 但这就是为什么我提到试图捕获广播的原因之一:强制检查它何时发生应该确保你总是得到一个新的有效的(如果版本检查通过它不应该),如果它可用的话。

Hopefully this helps~ 希望这有助于〜

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM