Google App Engine + APNS

Earlier this month, Google App Engine released support for outbound sockets and I figured that a Saturday spent mucking around with AppEngine to see if I could get it to work with APNS would be time well spent. In the sandboxed world of GAE, lack out outbound socket support meant that it was not possible to communicate with external services by opening a socket, which is what the Apple Push Notification Service (APNS) required. So for a long time, it was not possible to use the AppEngine to build an APNS provider, but now you can. Services like Urban Airship expose this capability in a way that can be consumed through a RESTful service, which works with GAE using UrlFetch, but the focus of this post is to communicate with APNS directly.┬áThere are some caveats though. Billing needs to be enabled, although the free tier should be sufficient for playing around, and there’s also the matter of the daily quota.

Here’s a whirlwind tour of getting yourself up and running on APNS with Google AppEngine.

1 – Fun with certificates and keys

Apple makes the job of working with APNS quite a fun and intellectually stimulating experience, if you have nothing else to do on a Saturday. You may also notice a couple of new gray hairs once you’re done, but at the same time, there is an elegance to the architecture that must be acknowledged, even though its painful to setup.

Generate a new certificate signing request
Fire up the mac Keychain Access tool and request a certificate from a certificate authority.
Request a certificate from a CA
In the resulting dialog, enter your email address an identifiable string in the common name field. Also, select the “Saved to disk” option, since we need to upload it later to the provisioning portal.
Certificate assistant
Once you’re done with this, you should have a Certificate Signing Request (CSR) in your file system.

Create a new App Id
Now head over to the Apple developer site, log in with your developer credentials and┬ánavigate to the iOS Dev Center, where you should see a link to “Certificates, Identifiers and Profiles” as shown below.
iOS Developer Program
First, create a new App Id, by navigating to that section:
New App Id
In, the add screen, enter any description and select the “Push Notifications” check box:
Push notifications
Also, in the bundle ID section, remember to include an explicit fully qualified bundle Id in the reverse domain notation, as wild-cards are not supported for push notifications:
Bundle Id

Create a new push certificate
Now, navigate to the certificates section, and create a new one. During creation, select the combo box as indicated below:
Development certificate
Next, select the app Id created earlier and when prompted, upload the Certificate Signing Request created earlier. If all goes well, the certificate will be generated. Download this certificate, and double click it to open it in the KeyChain tool. You would see the private key with the common name that you entered earlier when you expand the certificate. Remember to note that the certificate name is prefixed with “Apple Development IOS Push Services”. Select both the certificate and the key, right click and “Export 2 items”. It will prompt you to enter the KeyChain password and will generate a .p12 file that you will need later to configure the server side provider.

Generate a provisioning profile
The last step in this process is to generate a provisioning profile so that you can deploy the app on to the device. In the devices section of the portal, create a new device and enter the 40-character device Id you get from iTunes or the Xcode Organizer. Head over to the Provisioning Profiles section and create a new profile. Remember to select “iOS App Development as shown below:
Provisioning profile
In the next screens, select the App Id, device and certificate created in the previous steps to create the provisioning profile. Download the profile and drag it onto the profiles section of the Xcode organizer.

Now the painful part is done. Time to do some real work.

2 – Create the web service

A pre-requisite for this tutorial is Google App Engine, and getting a service up and running on it. If you haven’t done that before, follow the steps outlined in the getting started page and it should give you a good idea on how to work on this platform. It comes with good Eclipse integration so it should be a snap to get setup.

The framework I’ve used for APNS is java-apns which provides a simple API to APNS. Here’s all of the code I used to build out the simple service, this could be done in a simple servlet or a RESTful service on a JAX-RS implementation like Jersey for example:

InputStream inputStream = context

ApnsService service = APNS.newService()
.withCert(inputStream, "password").withSandboxDestination()

String payload = APNS.newPayload().alertBody(message).badge(1).build();

ApnsNotification notification = service.push(token, payload);

A couple of things to note, the .p12 file exported from the Keychain needs to be included in the war file (preferably in the WEB-INF directory to prevent public access) and password protected at export time. Also, it’s important to add the “withNoErrorDetection()” method as shown above as it would otherwise try to spawn threads to detect errors and would not run in the GAE environment since thread creation is restricted. The input into this web service is a 40-character token that is received from the device, and the message that is to be sent.

At this point, the server side work is done. Let’s move over to the client.

3 – Create the iOS client

For the purpose of demonstration and testing, I’ve created a simple single view application with the bundle ID specified in the provisioning profile.

The key methods you would need to implement in the AppDelegate would be:


1) -application:didFinishLaunchingWithOptions:
This method gets invoked when the application finishes launching either directly or when launched through a push notification. In the case of the latter, the details of the push notification are passed in through a dictionary object so that it can be dealt with. Here’s the code to register for push notification alerts:

[[ UIApplication sharedApplication] registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound];

2) -application:didRegisterForRemoteNotificationsWithDeviceToken
This method gets invoked with the device token received from APNS. This token uniquely identifies the device and is not the same as the UDID. The token needs to be sent to the web service so that it can pass it on to the APNS and have messages sent back to this device. This token includes some special characters and spaces which needs to be removed as shown below:

NSString *token = [ deviceToken description ];
token = [ token stringByTrimmingCharactersInSet:[ NSCharacterSet characterSetWithCharactersInString:@"<>"]];
token = [ token stringByReplacingOccurrencesOfString:@" " withString:@"" ];

3) -application:didFailToRegisterForRemoteNotificationsWithError
This method gets invoked if there’s some error in registering for remote notifications which causes the push token to be not available for the app.

4) -application:didReceiveRemoteNotification
This method can be used to trap an incoming message while in the app, and take some action. In this case it just shows it in an alert view.

UIAlertView *alertView = [[ UIAlertView alloc ] initWithTitle:@"Push Alert" message:userInfo[@"aps"][@"alert"] delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[ alertView show ];

To test this capability, I’ve built a test app that takes input text from a text field and sends it to the web service created in GAE. The resulting push notification is trapped and displayed in an alert view as shown in the sample code above.


Finally, a couple of things to keep in mind when developing apps that use push notifications:

  • It’s inherently unreliable, do not use it for transferring any critical information
  • While the transport is secured through TLS, it’s still advisable not to use APNS for company confidential information
  • Do not store your certificates in an accessible location on the web server. Password protect it for additional security
  • Store the device tokens safely on the server side, or users will be very upset if its compromised
  • It’s a good practice not to update information in the push notification handler code, since it may trigger updates without the user’s knowledge

That’s all for now. Enjoy!


A boy’s first computer

The week so far has been an eventful one. Being bed-ridden has made me pensive and nostalgic about my childhood, and long for the simpler days. I was specifically dwelling on the subject of interpreters and compilers which took me back to when I was nine, when I asked my uncle, who I considered as the pre-eminent guru in all things computers at the time, how to compile a .bat file.

At that time I was given an old 286 to play with. And when we moved around, so did my computer. Every week I flip open the large case case using a convenient latch on the two sides and peek in. I was enamored by the machine and eventually learnt what some of its parts were, and wondered how they worked. I sought books and the help of my uncle to learn about it. I once spent a weekend at my uncle’s where he showed me the difference between dir /p and dir /w, and told me to try it out for about twenty minutes while he went to speak to someone. He taught me the basics of DOS which I was usually very eager to try out on my own machine.

After I was done peeking, I usually close the box up and meticulously clean it. It was kept in perfect condition next to my work desk on a blue color custom built table for a computer which had a pull out keyboard and a place to keep a printer as well as some shelves below for various things. It was pretty big by today’s standards, but then everything was so. The computer case was about 2.5′ x 2.5′ x 10″. It was big, I couldn’t carry it by myself but I made sure I packed it safely during my vacation trips.

It also featured a 4 MB hard drive, 1 MB of RAM, a 14″ monochrome monitor and a 5.25″ floppy disk drive. There was a lot of trial and error to figure it out and spent many late nights trying to understand DOS, WordStar, WordPerfect, DBase III+, BASIC, Lotus 123. The command line baffled me, and piqued my interest, and I learnt to love the blinking cursor on the green screen waiting for the next command to be input.

It was a used machine at the time, so it came with some customizations and funky DOS shell like interface which was navigable through function keys, but also let you escape into the shell. I spent a lot of time trying to figure out how it worked and how to modify it. It also came with a couple of games which I still fondly remember: digger, pacman and paratrooper. I played very little games after that. I recently tracked this down to skill-envy (a pseudo psychology construct that I just coined), as playing games made me wonder too much how it was constructed, and not having the skills to build a similar game myself made me envious of the game author and the knowledge of the black art he possessed. Hence I preferred to stay away from games. I know, it’s childish, but in my defense I was a child.

Part of this black art was machine language. Printing the contents of .exe files showed a series of unintelligible characters and yet the only executable programs I could create at the time were plain text and readable .bat file. That was when I asked my uncle how I could convert a .bat file to the .exe file which I viewed as being inherently superior due to its mysterious nature. Knowing what I was trying to get at, he suggested I learn QuickBasic. I only had GWBasic installed on the computer. I came to realize that the syntax of QuickBasic was more or less the same, minus the explicit line numbers, so I taught myself GWBasic on my 286. Later I got a copy of QuickBasic and lo and behold, there was an option to compile programs into the mysterious .exe file format that I can directly execute from the command line. This revelation was a turning point for me and I was hooked on QB.

Having outgrown the 286 I pestered my father to purchase a newer computer, and this time a 66MHZ 486 DX2 with the “turbo” button. If turbo was turned off the computer ran slower, which baffled me. The computer also featured a 40 MB hard drive. That should last forever, I thought at the time.


After much internal debate and turmoil, I finally succumbed to the idea of purchasing a Kindle. I must say that I’m quite pleased with the product, having been an early adopter of the Sony Reader and paying dearly for it, with the added insult to injury when Sony decided to drop support for it’s PRS 500 on the Mac a couple of years later. Yes. I own a Mac now. I cannot ever imagine visiting the Free Software Foundation again, having turned over to the dark side so radically by purchasing more than one DRM-infested, anti-libre product of the agents of darkness in the same year.

Back to the Kindle. It’s got a great big 9.7″ display that’s very crisp. The battery life is good, and e-ink technology just seems to be getting better. Screen repainting has room for improvement – I don’t see much of a difference between my three year old Sony and the new DX when it comes to the page refresh speed. I do see a marked difference in the sharpness of the image which makes reading PDFs with small text much more easy to handle. The auto rotating screen is nice except when trying to read in bed and if you don’t mind reaching out awkwardly to flip the page. The Sony Reader on the other hand has smarter button placement.

The highlighting feature is a cruel joke. Anything that requires you to maneuver a tiny joystick to select text clearly hasn’t considered the important market segment with hand-eye dis-coordination. Also, the placement of the said joystick – otherwise referred to as a 5-way controller – is poor IMHO. The DX is also great for magazines and PDFs with it’s large form factor. The built-in 3G is dangerous and runs the risk of bankrupting the Kindle owner.

I’m curiously watching the Kindle’s forays into social features such as showing the popular highlights by exploiting the naivete of users that opt to store their highlighted text on the Amazon servers for safekeeping.

In summary, I do love my new Kindle, despite its shortcomings.

Debian packaging with git – Part 1

Recently, I’ve been taking a look at tools to version control and maintain my Debian packages in git.

Git, like mercurial, is a distributed SCM used to maintain the Linux kernel since version 2.6.12. Branching in git is very cheap, and merging is trivial and follows a decentralized model where developers can push and pull code with each other in true distributed fashion.

Of the Debian tools I’ve tried, the main contenders are:

  • gitpkg
  • git-buildpackage

gitpkg, is extremely simple to use, and quick to get you off the ground. If you already have an entire revision history of .dsc, .diff.gz files, maintained in the good old fashioned way, gitpkg provides the git-debimport utility that lets you import everything into a git repository in one go. It does this intelligently by applying consecutive revisions and tagging the different versions along the way.

Here are the steps that I took to import my ncc package history into git:

$ mkdir /git/repo
$ cd /git/repo
$ git-debimport ../../debian/ncc/ncc

It will then pick up all the files beginning with ncc in the ../../debian/ncc directory.

To see the revision history:

$ cd ncc
$ gitk

The .orig.tar.gz files will be extracted to a branch called upstream and tagged (v2.5), it will then be merged to master and the .diff.gz files applied sequentially and tagged at each step (v2.5-1). A list of tags like the following will be created:


To create the source package for a particular revision:

gitpkg v2.6-1 v2.6

Where the first argument is the tag with the Debian changes, and the second argument is the tag for upstream code.

$ ls -F ../deb-packages/ncc/
ncc-2.6/ ncc_2.6-1.diff.gz ncc_2.6-1.dsc ncc_2.6.orig.tar.gz
$ cd ../deb-packages/ncc/ncc-2.6
$ debuild

These steps didn’t work for me the first time as git silently dropped an empty directory that caused the build to fail. The workaround was to create a .gitignore file in the empty directory. This is probably something that gitpkg could be configured to handle.

To upgrade to a new upstream version:

$ git checkout upstream
$ rm -rf *
$ tar zxvf /path/to/new/upstream.tar.gz
$ git add .
$ git commit -m
$ git tag v2.7

# Merge the Debian changes
$ git checkout master
$ git branch debian
$ git checkout debian
$ git merge upstream

# Fix conflicts / make Debian specific changes / test

$ git add .
$ git commit -a
$ git checkout master
$ git merge debian
$ git tag v2.7-1

# Generate Debian package artifacts
$ gitpkg v2.7-1 v2.7

# Build Debian package
$ cd ../deb-packages/ncc/ncc-2.7
$ debuild

A couple of caveats – gitpkg generates the orig.tar.gz by tarring up the upstream branch. As far as I know, gitpkg does not yet have pristine-tar support yet and that’s a must-have if you don’t want to re-package the upstream sources. I also noticed that git-debimport had trouble with absolute paths, for which I submitted a patch – so I don’t have a whole lot of confidence in the tool yet, but it’s getting there.

FireFox + GPG

FireGPG is a neat little FireFox plugin that acts as a front-end for GPG and provides seamless integration with Gmail. Once installed and Gmail support is enabled (which is, by default), a series of signing/encryption related buttons will appear at the top of the Compose Mail page.

It also lets you easily encrypt or sign any selected text area on a web page.

It’s a very intuitive and effective plugin. I just wish I had stumbled upon this sooner.