{ 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.

May 20, 2010

Lessons learned - iPhone Review

I'm writing for the Synyx GmbH & Co. KG mobile solutions blog. From time to time, I'll cross post articles here, if I think they are of interest for you. If you'd like to read all of my other posts, subscribe to the Synyx Mobile Solutions Blog.


When you submit an App to the Apple App Store it has to go through a "rigorous quality check", conducted by Apple. Although there are plenty of resources out there, here's a short rundown of what we've learned ourselves so far:

  • Marketing Apps are not allowed

  • If the sole purpose of your App is marketing, you'll have a hard time getting your App through. You need to add what Apple calls "user functionality". That could be something simple like a photo gallery or a feature to reserve a room or table.

  • You cannot tease your users with features that they have to pay for

  • If you are offering a lite version of your App, you cannot add disabled functionality, which would be enabled in the paid version. A lite version usually is offered separately from a paid version, which means the user will constantly see disabled menu items or buttons, since the App will never be updated. Instead add a info section about the paid version in your App, which describes what the paid version offers.

  • Don't ask your users to upgrade

  • You cannot add an alert in a free/lite version of your App, which asks users to upgrade or buy the paid version. Instead you should add a "buy me" button or a section in your App further describing what your paid version offers.

  • Build a working App

  • You are definitely rejected if your App is buggy! If the reviewer thinks he found a bug, he'll reject your App. A crash is the worst case scenario, but it happens. However, don't depend on Apple as your QA, because the review times are too long to go back and forth this way.

  • Don't infringe Trademarks or Copyrights

  • Don't mention Apple, Android or any other Trademark therefore - as long as you don't own it. You should also resist to use iPhone like icons or images.

If you respect all of these restrictions and gotchas, you should be save to get your App through the review process. I say "should", because it all appears to depend on the person who reviews your App. Let us know what you experienced, submitting your Apps, I bet there are a lot more of these gotchas.

May 10, 2010

Don't Forget your Linker Flags

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.

Doublemill is out the door and available for download in the App Store - finally! It has been more than two weeks since my submission. The reason why it took so long, besides Apple, which takes up to a week at the moment to review Apps, is my stupidity!

I'm using Objective-C bindings for YAJL to create and parse JSON in Doublemill's multiplayer feature. It comes with a Category for NSString, which basically makes it a two liner to create a JSON representation of a string:



Okay it's not a two liner, but it's close! Anyways, in order to add this library to your project, one way is to download the build and add the static library to your Xcode project. It'll work seamlessly in the Simulator. If you want to deploy it to your iPhone or any iPhone, you need to add linker flags:

Under 'Other Linker Flags' in the Test target, add -ObjC and -all_load (So NSObject+YAJL category is loaded).


This is very common and no big deal actually. If you want to know more about why you need this, check out the Apple Developer Connection.

I added those flags for the my development environment and also for my beta testers. However, I totally missed this in my Xcode AppStore build configuration settings and since you cannot really test your final build, it went in review without those linker flags.

The reviewer at Apple found the bug, which even resulted in a crash of Doublemill. I'm grateful they found it, however I'm not really happy, that I had to wait another week to get Doublemill out the door. In the end it was my mistake and I'm sure in the future, I'll make sure to have those build profiles setup more carefully.

May 03, 2010

iPad Apps have priority

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 had to wait for a week, after submitting Doublemill Premium for review to the App Store, until Apple decided to have a look at it. Unfortunately, we were rejected - for a good reason! As it turned out, I didn't link my libraries correctly, which turned out to cause a crash every time you wanted to play online, but I digress...

It took me roughly 2-3 hours to find the bug, fix it and resubmit the App. Now I'm waiting for five days again.

Yesterday, I finished polishing Doublemill for iPad, after reworking the UI and implementing a nicer Player vs. Player experience. Since it was a rainy day and there was only Star Trek on TV, I decided to submit it for review, since it would take at least a week until they had a look at it. I want to be ready for the European start of the iPad and if there's anything wrong with Doublemill for iPad, it would take at least 2 weeks to get it into the App Store - that's what I thought!

After the usual email, you get after submitting, I instantly received another, saying my App is in review. Just like that - without waiting for a week. That got me really upset! I invested almost 4 weeks of my spare time, to gett Doublemill Premium ready and polished and I had to wait for a week until it was in review.

To me this is a clear signal, that iPad Apps are more important to Apple than iPhone Apps - at the moment. I hope this will balance again soon. It is understandable, that they want the iPad App market filled as soon as possible, but that's no reason to make the iPhone App developers wait more than a week. That takes us back to where we were a year ago: waiting and waiting and waiting - just to be rejected!

com_channels

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

recent_postings

loading...