Universal launch images with PhoneGap

I’ve been playing with PhoneGap a lot recently, in part to prepare Marbles2, but also to bring JS Console to the iPhone as a native app. I’ve always wanted to create an app that worked on all devices, but getting the launch image correct for each device can be tricky.

How the launch image works on PhoneGap

Basically there’s two launch images. Once for the native app and once (manually by PhoneGap) whilst the UIWebView (aka Safari) is loading up. The native one is handled by the app as per the documentation on the Apple developer site, but the overlaid image is hardcoded to ‘Default.png’. This is what we’ll fix.

Changes to PhoneGapDelegate.m

To get the three devices to work properly, you need to make a change to PhoneGapDelegate.m. Changing the following line:

UIImage* image = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Default" ofType:@"png"]];
imageView = [[UIImageView alloc] initWithImage:image];
[image release];

To:

UIImage *image = [UIImage imageNamed:"Default"];
imageView = [[UIImageView alloc] initWithImage:image];
// [image release]

† Note that I’ve not learnt Objective-c, I’ve just messed around and Googled enough to get to this point!

imageNamed

The reason we switch from initWithContentsOfFile to imageNamed is for two reasons:

  1. initWithContentsOfFile is also using the bespoke pathForResource which returns the full path to the file, which we don’t want as I’ll explain.
  2. initWithContentsOfFile apparently doesn’t correctly pick up the @2x resources for the iPhone 4 retina displays

Adding the Launch Images

Now you need to create three images, for:

  1. iPhone 3GS and below
  2. iPad
  3. iPhone 4 double resolution

The details of the resolutions are available Apple’s developer reference.

The iPhone 4 image is easy, you call it [email protected] and drag it in to the xcode project. The iPhone 3GS (and below) image is called Default.png and also dragged in to the project (there will probably already be a phonegap default image that you’ll overwrite). Finally the iPad image needs to be called Default~ipad.png.

This only works because we’ve made the change to use initWithImage because it’ll automatically detect the device type and add the extension.

One Final Tip

If you notice that when your app loads the launch image jumps, it’s because the phonegap UIWebView is (incorrectly) offset by negative 20 pixels – we can fix this too.

Michael Brooks wrote a really elegant little bit of code that fixes the offset in the web view that’s also contributing to the launch image jumping.

Add the code from this gist http://gist.github.com/510407 to your *AppDelegate.m (in that if your app is called jsconsole, add the code to jsconsoleAppDelegate.m).

Once that code is in, you’ll have your universal phonegap app with launch images all in the appropriate size for the app.

I used this technique for the iOS version of JS Console (though I’m not totally sure it’ll get accepted to the itunes store!!!).

Finally, if you want to learn more about PhoneGap, my conference Full Frontal, is running a full day workshop with Brian LeRoux entirely on PhoneGap, so check it out!

9 Responses to “Universal launch images with PhoneGap”

  1. I had to add quite a bit more code for my iPad app to be accepted. Basically, one launch image won’t do – you have to support all the ways the iPad can be oriented. If you app only does landscape and not portrait, you still have to support both landscape left and right.

  2. PhoneGapDelete.m ….i don’t see this file in my xcode phonegap setup. the only classes are AppDelegate.h and AppDelegate.m. any pointers would be great.

    thanks.

  3. @joshk – it’s one of the files installed by the PhoneGapInstaller thing – so I’d search your drive for the file (mine’s in Documents/phonegap-iphone/PhoneGapLib/Classes)

  4. found it. in mine the file name is PhoneGapDelegate.m……not PhoneGapDelete.m

    thanks for the reply

  5. @joshk – ah – that was just a typo – thanks for pointing that out.

  6. This: UIImage *image = [UIImage imageNamed:"Default"];

    Should be: UIImage *image = [UIImage imageNamed:@"Default"];

    You need to use an @ when working with strings ;-)

  7. Thanks a lot for this post, it was exactly what I needed to fix the startup image in the iPad version of my game/app.

  8. Zomg this is so fucking useful. Thanks!

  9. Just stumbled across this, the reason you have to use imageNamed for this is a known bug with Apple on initWithContents of file. Using imageNamed is not an ideal solution really as all the images hang around in memory, I pretty much avoid using imageNamed at all costs.

    It might be more efficient while the bug is around to do a test for if @2x needs appending to the filenames, but if it’s not for lots of big images or you are re-using the images, for icons in a tableView maybe, then imageNamed is good, just use wisely :)

Leave a Reply
Not required

CODE: Please escape code and wrap in <pre><code>, doing so will automatically syntax highlight