获取iOS设备的GCM推送通知注册令牌的正确步骤是什么?GCM是否不可靠?

14

嗨,我已经按照iOS上使用GCM的教程进行了操作。它一直表现得很不稳定(这意味着所有证书、权限等都没问题)。然而最近,我一直在收到两条错误信息:

GCM | GCM registration is not ready with auth credentials.

此外,重新连接到GCM时失败,并显示以下内容:

Error Domain=com.google.gcm Code=501 "(null)"

部分原因是设备没有获取到GCM注册ID。是否还有其他人最近更频繁地遇到过这些问题?或者是因为我调用GCM API的顺序不正确(特别是connectWithHandler:startWithConfig:tokenWithAuthorizedEntity方法)?我怀疑原因是后者,因为我在一段时间之后确实会获得GCM ID。

我并不总是会收到GCM ID。当我没有收到ID时,通常需要通过Xcode运行应用程序一两次(或强制关闭应用程序)。显然,我的用户不应该做这些事情。

这是我调用GCM API的顺序:

  1. 设备获取APNS令牌
  2. 我使用我的APNS令牌调用tokenWithAuthorizedEntity:
  3. ^ 这通常会导致上述两个错误之一。
  4. 每当我确实需要GCM令牌时,我通过再次调用tokenWithAuthorizedEntity来强制重新获取GCM令牌。

此外,我还在我的applicationDidBecomeActive:方法中编写了connectWithHandler:调用。

几个问题:

  1. 如果我只对接收GCM推送消息感兴趣而将它们发送给上游,那么是否有必要在applicationDidBecomeActive:中调用connectWithHandler:
  • 如果问题1的答案是肯定的,在该方法的完成处理程序中,如果出现错误,并且此时我没有GCM令牌,那么我应该再次尝试获取令牌吗?(即调用tokenWithAuthorizedEntity?)
  • startWithConfig应该在何时调用?在获取GCM令牌之前还是之后?
  • 编辑:有限的测试显示以下内容似乎有效:

    1. 首先获取GGLInstance ID(即调用getIDWithHandler:
    2. 如果上述GGLInstance ID没有任何错误,请请求GCM令牌(即调用tokenWithAuthorizedEntity:
    3. 这样通常会产生以下错误,但至少在短时间内(~3-10秒钟),令牌就会被接收:
     

    无法在缓存中找到令牌 错误域= com.google.iid Code=-25300  “(null)”


    我正在使用GCM与iOS,因为我认为它使事情变得非常简单。虽然我还没有遇到这些错误。请发布您的注册代码,我将与我的进行比较。 - Rob85
    如果您按照 Google 的 GCM 示例操作,就不会出错。我建议您检查所使用的证书,确保它们与授权凭据无误。 - Rob85
    什么是认证凭据错误?如果存在证书错误,推送在第一次就不会起作用。 - Kedar Paranjape
    针对上述错误,我建议您按照文档中的建议实施重试机制,如果问题仍然存在,请向其中一个支持渠道报告此问题。请参阅此处有关5xx错误的描述:https://developers.google.com/cloud-messaging/http-server-ref#error-codes。 - Kay_N
    2个回答

    4
    在applicationDidBecomeActive中调用connectWithHandler:方法是否必要,如果我只对接收GCM推送消息感兴趣而不发送消息上行?
    是的,connectWithHandler是必需的,因为它的主要目的是与GCM端点建立连接。
    如果答案是肯定的,在该方法的完成处理程序中,如果发生错误,并且此时我没有GCM令牌,那么我应该尝试再次获取令牌吗?(即调用tokenWithAuthorizedEntity?)
    所以它应该工作的方式是在请求令牌时检查错误,如果请求失败,则使用指数退避重试。更多信息 这里。另外,请阅读注释 这里。现在,如果您仍然想在任何时候重新调用 GGLInstanceIDTokenHandler,则在获取新令牌之前还应实现deleteTokenWithAuthorizedEntity

    应该在何时调用startWithConfig?在获取GCM令牌之前还是之后?

    在您的AppDelegate.m中,您应该使用startWithConfig方法调用GGLInstanceID共享实例。在GGLINstanceID.h类中,它应首先获取一个实例ID,然后将项目授权为已授权实体,最后通过iid服务获取注册令牌。请参见GGLInstanceID.h类的详细实现here
    希望这些答案能够帮到您!
    编辑 this是否解答了您的问题?它的要点是,请确保您的目标Bundle标识符与info.plist文件中的BUNDLE_ID相同。
    希望这可以解决错误,如果没有,请告诉我们测试时发生了什么,我们可以从那里开始。 :)

    你的意思是这些步骤应该严格按照顺序进行吗?1)获取GGLInstance ID(通过getIDWithHandler:) 2)然后调用tokenWithAuthorizedEntity:? (这意味着我只能在成功获取(1)中的Instance ID时才能在(1)的完成处理程序中调用(2)。) - Kedar Paranjape
    我不太确定顺序的严格性,但根据逻辑,在获取令牌之前必须先使用GGLInstanceID,因为此令牌是通过实例ID服务生成的,除非应用程序实例初始化此实例ID,否则它如何分配令牌呢? - Kay_N
    关于TokenWithAuthorizedIdentity; 我不能确定它应该属于哪里,但据我所知,在设备检索令牌之前,项目授权也很重要。 - Kay_N
    总之,根据我的理解:注册令牌将具有对应于特定设备上特定项目的应用实例的认证凭据。请注意,对于第一个应用程序实例,GCM 必须识别“abc”设备上的“xyz”项目,以便将通知传递到其精确目的地。希望这有意义。 - Kay_N
    好的,明白了。我会在测试过程中继续尝试,并在这里汇报结果。 - Kedar Paranjape
    显示剩余3条评论

    1
    尝试将connectWithHandler块移动到didFinishLaunchingWithOptions方法中,在获取gcmConfig块之后。(对于官方示例,在[END start_gcm_service]之后)

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接