Thu 14 October 2010

How to properly ask a girl to Homecoming

Before we get into this, I'll note that this post is actually about mobile web development, not the romantic adventures of anyone in particular. You've been forewarned.

Sometimes in life, you feel as though doing things the "ordinary" way just doesn't cut it. I've found this to be a common theme in my work, and I'm not the only one who operates this way. One example is my brother (one of them, at least). I recently dropped by my parents house for a visit as I plan my next trip, and I was catching up with him as we walked up to a store. We somehow ended up discussing his upcoming Homecoming dance, and how there's some girl that he wanted to ask, but in doing so go above and beyond the normal methods.

I sat there and sarcastically threw ideas at him for about 5 minutes, as I'm prone to do when I'm bored. One of them involved using a spare iPhone I recently came into possession of to display some message to her. He decided to take it one step further, and asked me if I could help him craft a simple game that, upon winning, would ask her to the dance.

I found myself thinking the idea was pretty awesome. To make that long story short, we built it, she liked it, he's happy, I'm awesome, and the world keeps on a-spinnin'. The game can be found at the following link - best viewed on an iPhone, but should still be beautifully awesome on any device (Android, PC, WebOS, etc):

Give the game a whirl

Oh hallo thar Mobile Safari

So, making the game was an interesting experience. I opted to build it in a Webkit wrapper - HTML/CSS/Javascript are a much faster way to prototype, and I wasn't looking to spend 12 hours on this project (I somewhat did, but not for the reasons one would think offhand). The process we took was pretty simple - sat down, sketched out the game play and general UI, then started building; I, of course, actually implementing things in the tech sense, and my brother handling the artwork/color scheme/etc. Building the game, all said and done, took us around an hour and a half from start to finish.

At this point, I figured, let's Phonegap it up and call it a day. This would've worked, except for the fact that Apple has apparently blocked newer i(Phone|OS) SDKs from running on Leopard. I've since upgraded to Snow Leopard, but seriously, this seems a bit overbearing to me.

Of course, at that point, I wasn't going to upgrade my OS then and there, as it was past midnight. I experimented with reverting the firmware back to the 2.x series, which I'm able to build and target to, but there were a myriad of problems there due (apparently) to some earlier jailbreaking that had occurred with the device. Go figure.

As a last resort, I decided to bookmark the app on the phone to "install" it. The one caveat with this approach is that it'd require an internet connection upon opening it up every time. What'd be ideal is if we could jam the entire thing into the Mobile Safari cache - there's a simple trick here that'll make life easier. I found that Mobile Safari, by default, won't cache sites like you think it would, but you can supply it with an HTML5 Cache Manifest that'll be respected by the browser, forcing everything to get shoved in the cache.

The cache isn't huge, though, and the initial load shouldn't be huge as a principal. There are a lot of external scripts used here, mainly to automate smooth CSS transitions so the device hardware accelerates animations, so the entire app is roughly ~130kb. Small, in this case, but the limitations were worth discussing.

To get around cold cache loads, the single image used in the game (the strawberry) is Base64 encoded into the html file itself, and all scripts are also placed inline. Combine this with a few Apache directives, and it loads quick enough the first time. The final trick is the following:

# At the top of your file, specify the cache manifest (your_app.html)
<html manifest="dragonfruit.manifest">

# The cache manifest itself (dragonfruit.manifest)
CACHE MANIFEST
index.html
apple-touch-icon-precompressed.png

# Needs to be sent back to the browser as a header for the manifest (.htaccess, etc)
AddType text/cache-manifest .manifest

In there, we modify three files. In the app itself, specify the location of the cache manifest; the second set is an example cache manifest you can borrow (the icon is used in the bookmark flow for the iPhone); the final piece is a header that needs to be sent downstream to the browser when the manifest is requested.

Voila, we've installed an app onto the iPhone without compiling anything. Shove it all into the cache, and it can sit there for quite some time - if we were to combine it with some localStorage action, it's an (almost) potent combination. It still doesn't beat the App Store for distribution, but hey, it worked.

Ryan around the Web