{ by david linsin }

May 28, 2010

Apple Push Notifications Gotchas

Last year, I worked on a Nine Men's Morris (Mühle) implementation for Android, called Doublemill. Since I'm an iPhone user, I decided to port the game to iPhone/iPod touch and the iPad. There are 3 versions: Doublemill Premium, Doublemill Lite and Doublemill for iPad.

I'm implementing Apple Push Notifications (APN) for Doublemill Premium right now and ran into some gotchas, which I'm pretty sure are implemented somewhere else, but I'm gonna share them here with you. If you are new to APN, checkout Apple's documentation. It's pretty good and will get you quite far.

The first problem I ran into, had to do with my provisioning profile for development. I enabled APN in my Provisioning Portal, installed the certificate and implemented all the delegate methods according to the documentation, but somehow the method

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error


was called with error code 3000 - "no valid 'aps-environment' entitlement string found for application". I was pretty sure, I setup everything correctly. However, I missed one little thing:

After you have generated your Client SSL certificate, create a new provisioning profile containing the App ID you wish to use for notifications.


That's what the Provisioning Portal tells you to do after you enabled APN. Your existing provisioning profiles are not being hooked up to APN, you really need to create new ones.

Another problem I ran into is a blocked Wifi port. Apple's documentation says:

If a cellular or WiFi connection is not available, neither the application:didRegisterForRemoteNotificationsWithDeviceToken: method or the application:didFailToRegisterForRemoteNotificationsWithError: method is called. For WiFi connections, this sometimes occurs when the device cannot connect with APNs over port 5223.


That also means neither of the methods is called when 5223 is blocked. Fortunately I came across a very helpful post on the Apple Developer Forums (sorry can't link to that here), which pointed me to a mobileconfig, enabling APN logging. If you have your phone connected and can see the log statements, you can find out if your port is blocked or something else is wrong. Don't forget to restart your phone after installing the mobileconfig, in order to enable the logging. For Doublemill the statements look something like this:

Connecting courier stream to sandbox.push.apple.com on port 5223

Connecting courier stream to push.apple.com on port 5223

Connecting to courier 2-courier.sandbox.push.apple.com

Connecting to courier 19-courier.push.apple.com

Connected to courier 2-courier.sandbox.push.apple.com (17.000.34.73)

Sending connect message with token 'xyz'

Connected to courier 19-courier.push.apple.com (17.000.36.88)
Sending connect message with token 'abc'

Recieved connected response OK

Sending filter message for enabled hashes { 34345 = "de.linsin.games.doublemill"; } and ignored hashes {}

...

Recieved connected response OK


These log statements are priceless, when hunting down the reason why you won't receive push notification in your application!

The last gotcha for today is one that I couldn't really find in Apple's documentation or at least I didn't really understand it that way. Anyways, if you distribute your App with an Ad-Hoc provisioning profile, which you would do for beta testing, the destination of your push notifications are not the sandbox, but the production. Come to think of it - it does make sense. However, you do need to create the production certificate and a new provisioning profile for it. Of course, your backend needs to be able to handle both destinations, as well!

Overall, APN is a cool feature and if you are running a server for your App anyways, it actually is for free! If your backend is running on Google App Engine, it's a different story, which I'll talk about in a future blog post.

1 comments:

safdar said...

Nice post with great details. I appreciate your info. Thanks for sharing.


com_channels

  • mail(dlinsin@gmail.com)
  • jabber(dlinsin@gmail.com)
  • skype(dlinsin)

recent_postings

loading...