Tuesday, June 23, 2009

Some Android Tips

There's a brand new update available for the Android OS, version 1.5 aka "Cupcake". My phone came with 1.1 and despite some prodding it wouldn't go ahead and upgrade itself. So I had to download the 1.5 updates and do it myself. That page is full of long and complicated explanations but basically you're just copying files, renaming them to update.zip and rebooting the phone, twice. (Mine got confused in the middle because it finally started to automatically update itself and I let it. If that happens just ignore it and continue with the manual process and everything should be fine.)

My main focus with tinkering with the phone has been to get the API demos running so I can get a sense for how easy it is to work with the Google MapView classes and also how much boilerplate code I need in order to load data over the network and draw pretty things with OpenGL. The Hello World tutorial worked straight away: if you have the phone plugged in it automatically installs your app and runs it on the device, if not then it fires up an emulator. Getting the API demos up and running was a little trickier because it involved importing the project fromandroid-sdk-mac_x86-1.5_r1/platforms/android-1.5/samples/ApiDemos first, but it did work after I upgraded to Cupcake.

For the MapView to work you need to jump through some app signing things before you can get a Google Maps API key that will allow the device to load map tiles. The documentation is quite dense but if you're just playing around in Eclipse you can sign things with your debug key; in this case the API key signup page tells you what to do. Just be sure to log in with the same Google account you'll be using in the Android Marketplace, if you get that far.

I decided to jump straight in and try my hand at an app that loads data from a web service and displays it on a map. The learning curve was OK, here's a list of things I wish I'd known about before I started:

  • Like any good Swing programmer or web app developer, I have a head for asynchronous operations and I'm comfortable with callbacks and so on. Of course Java is a little more verbose with this, and the need to run UI code on the UI thread but have long running tasks in a separate thread can quickly lead to spaghetti code. Thankfully Android has anAsyncTask class which really elegantly wraps up the pattern of bouncing between two threads and tracking the progress of long tasks. Completely recommended over lots of new Thread(new Runnable()).start(), not least because it lets you cleanly cancel things in onDestroy, too.
  • The Android libraries include the Apache HTTP library, which is quite good (if a little verbose). This HTTP & JSON example is great, and as I discovered if you reuse the HttpClient object your app will load lots of data happily and with good performance.
  • The android.util.Xml class will make you a SAX parser for XML parsing. This tutorial otherwise covers what you need to know about SAX parsing and Java if you haven't done it before. The Xml class's convenience function cuts out the AbstractThingerFactory boiler-plate code that Java programmers are generally too tolerant of.
  • In MapView, an ItemizedOverlay with no items still needs to call populate or your app will crash as soon as you interact with the map. This is a known issue, I'm not sure if it's a bug, I'm mainly noting it here for search engines.
  • It turns out Activity.onCreate—the standard entry point for Android apps—gets called if the screen rotates, which happens if you open the keyboard on the dev phone/G1. If you used onCreate to fire off a bunch of threads and load data, you need to drop those threads in onDestroy, pass a copy of the data you want to keeponRetainNonConfigurationInstance, and get it back withgetLastNonConfigurationInstance. The Android Guys explain all this and more in a three part series, but the second part was most useful to me.
  • Compilers and code generation and XML config files are all fine, but the Android manifest file is king. If you're using the Google MapView library you need to declare this in the manifest or your app will unceremoniously crash.
  • Likewise if you're using the network or asking for location information, you'll need to add the relevant permissions to the manifest, or your app will fail (with no explanation). I'm not sure why this is the case, and why the SDK even lets you compile an app that requires internet access without prompting you to add the INTERNET privilege, but it does. As far as I can see these permissions aren't exposed to end users, but perhaps they'll help people navigate the Android Marketplace once there are devices out there with varying capabilities?

All in all it took me just over a day to get to the point where I felt confident that the phone was doing what I was telling it, and that there wasn't too much magic and surprise crashes were rare. The next thing I want to investigate is the OpenGL ES implementation

No comments: