Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper sequence to get registration token for GCM push notification on iOS? Is GCM unreliable?

Hi I've followed the tutorial for using GCM on iOS. It has been working intermittently(which means all the certificates, permissions and stuff is okay). However of late, I have been getting the two error messages repeatedly:

GCM | GCM registration is not ready with auth credentials.

Also, reconnection to GCM fails with:

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

This co-relates,in part, to the device not getting a GCM registration ID. Has anyone else come across these issues more frequently of late? Or is it because I'm calling the GCM API in an incorrect sequence (especially the connectWithHandler:, startWithConfig: and tokenWithAuthorizedEntity methods)? I suspect that the reason is the latter since I do get a GCM ID after some delay.

I do not always receive a GCM ID either. When I don't receive one, I usually have to run the app once or twice more via Xcode. (Or by force-closing the app). Clearly this is not something that my users should have to do.

This is the sequence of my GCM API calls:

  1. The device gets an APNS token
  2. I then call tokenWithAuthorizedEntity: by using my APNS token
  3. ^ This usually results in one of those two errors mentioned above.
  4. Whenever I actually need a GCM token, I force a refetch of the GCM token by calling tokenWithAuthorizedEntity again.

Also, I have the connectWithHandler: call written inside my applicationDidBecomeActive: method also.

A couple of questions:

  1. Is the call to connectWithHandler: in applicationDidBecomeActive: necessary if I am only interested in receiving GCM push messages and not send them upstream?
  2. If answer to (1) is yes, in the completion handler of that method, if an error occurs, and I do not have the GCM token at that point, should I try to get a token again? (i.e. call tokenWithAuthorizedEntity?)
  3. When should the startWithConfig be called? Before getting a GCM token or after?

EDIT: Limited testing revealed that the following appears to work:

  1. Get the GGLInstance ID first (i.e. call getIDWithHandler:)
  2. If the above GGLInstance ID was received without any error, ask for a GCM token (i.e. call tokenWithAuthorizedEntity:)
  3. Doing this generally gives the following error, but at least in a short while(~3-10 seconds), the token is received:

Unable to find token in cache Error Domain=com.google.iid Code=-25300 "(null)"

like image 719
Kedar Paranjape Avatar asked Nov 25 '15 14:11

Kedar Paranjape


2 Answers

Is the call to connectWithHandler: in applicationDidBecomeActive: necessary if I am only interested in receiving GCM push messages and not send them upstream?

Yes, connectWithHandler is necessary regardless as its prime purpose is to make connection with GCM endpoint.

If answer to (1) is yes, in the completion handler of that method, if an error occurs, and I do not have the GCM token at that point, should I try to get a token again? (i.e. call tokenWithAuthorizedEntity?)

So the way it should work is you check for errors while you are requesting the token itself and retry with exponential back-off if the request fails. More info here. Also, read the note here. Now, if you still want to re-invoke the GGLInstanceIDTokenHandler at any point you should also implement deleteTokenWithAuthorizedEntity before getting a new token.

When should the startWithConfig be called? Before getting a GCM token or after?

In your AppDelegate.m you should invoke the GGLInstanceID shared instance using startWithConfig method. Essentially in GGLINstanceID.h class, it should first get an Instance ID; then authorize the project as Authorized Entity and then get a Registration Token through the iid service. See the detailed implementation for GGLInstanceID.h class here.

Hope this answers help!

EDIT

Does this answer your question? Gist of it is, make sure the Bundle Identifier for your target is the same as the BUNDLE_ID in the info.plist file.

Hopefully this resolves the error, if not post what happened when you test it and we can go from there. :)

like image 104
Kay_N Avatar answered Oct 22 '22 11:10

Kay_N


Try move the connectWithHandler block to didFinishLaunchingWithOptions method, after you get the gcmConfig block.(for official's example, after the [END start_gcm_service])

like image 21
Chris Ho Avatar answered Oct 22 '22 12:10

Chris Ho