Fri 7 Jan 2011
I’ve had a long association with Java programming.
I started playing around with Java software development back in 1995, before the platform was even released as version 1.0. In 2001, I got my hands on a Siemens SL45i handset and began to develop using Java ME (known as J2ME at the time), a cut-down version of Java for embedded devices such as mobile phones. For a time, I worked for mobile games developer Glu (known as Macrospace at the time) porting games to different Java ME handsets.
That’s all just so I can say that I got to know a lot of the ins and outs of doing Java development for mobiles. Although, I haven’t really done much of that recently, and these days Java ME has fallen out of favour, with the rise of smartphones that support other software platforms. However, Android-based smartphones are now becoming popular, and Android applications are written using Java.
So, I was rather curious as to what developing on Android was like, and over the last couple of months, I’ve spent an hour or two every 2-3 days tinkering around with an Android project as a hobby. This was my chief diversion during the weeks after our daughter was born in November.
I didn’t do an Android course or read an Android book. I simply took what Google provided on Android and ran with it, to see what I would learn.
Google makes a lot of really good information and tools for Android available for free. I was able to easily set up a development environment on our laptop (an old Dell Inspiron 1501). Unlike if I’d been developing for, say, the Apple iPhone, I didn’t need to get a specific brand of computer, nor pay anyone to join their development program. In fact, they even make the full source code for Android available if you want to see how it works under the hood.
It made me think how empowering this is for people. In years gone by, if you wanted to tweak your car (or even build a car up from parts), you could easily get access to the information and tools to do it yourself. For modern cars, that’s not really the case. However, it is the case for your modern mobile phone, and given how important a tool it has become in our daily lives, that’s a really liberating thing.
In fact, our particular laptop has a comparable amount of grunt to a modern mobile phone (such as an HTC Desire), so it’s no wonder I find myself doing more tasks on a handset rather than this laptop. In addition, while with Java ME, it was common to test the software on an emulator (e.g. running on the laptop) before loading it onto a real device, but here, the inability of the laptop to emulate a modern handset at anything like real speed made that impractical. Also, the Android adb tool does a great job of exposing logging and debug information in real-time from devices, so there’s no real penalty in testing directly on the device.
Android development is theoretically done using the full Java SE, rather than the cut-down Java ME. While it is true that there is a lot more power and flexibility in the hands of developers than there was for Java ME, there are still a lot of wrinkles that make it unlike full Java SE.
Three examples of these wrinkles are:
- AndroidManifest.xml: This is a text file that is included in every Android app, and basically describes how the system should interact with the app. Instead of this being specified in the Java code, it needs to be separately documented here. For example, it specifies which icons appear in the list of launchable applications and which classes should be invoked when those icons are selected. It also specifies how other applications on the device might interwork with the app.
- Activity-oriented architecture: Every Android app is basically broken into components of four different types. These are the Activity (an interactive screen of some kind), Service (an invisible, background task), ContentProvider (a database-like interface to some content), and a BroadcastReceiver (waits for a system-wide event to perform a task upon). These components communicate with each other using a type of message called an Intent, which is typically a URI and some associated metadata. (My small hobby application used a ContentProvider, a Service, and several Activities.)
- Dalvik Virtual Machine: Instead of compiled Java bytecode running on a Java virtual machine (the typical approach for Java SE), the compiled Java bytecode is converted into Dalvik bytecode and that is run on the Dalvik virtual machine. This is a pretty clever way to allow developers to reuse the well-known Java tools but allow the Android system to operate outside of them. However, as the Java to Dalvik conversion doesn’t have full knowledge of the original source code, it seems to find it difficult to optimise things automatically, and leads to strange advice like manually copying class fields into local variables to make execution more efficient.
Another interesting thing, from a mobile developer perspective, is that Android manages a “stack” of screens (Activities) in a similar way that was done for the old WAP/WML 1.1 browsers (and HDML browsers before them). The developer can push screens onto the stack in various ways, while the user hits the back button to pop them off. Given that this approach was dropped from the newer versions of WAP (and in the newer mobile browsers that followed), it is with some nostalgia that I see it come back again. However, it does make a lot of sense for mobile handsets and their small screens (i.e. the impracticality of having several windows open side-by-side).
While the Android SDK gives the developer a lot of power, it wasn’t as easy to use as I’d hoped. Not that Java ME was easy, by any means, but Android’s design and development has probably resulted in some strangeness that Java ME avoided.
You have to remember that Java ME evolved in a (some would say ponderously) slow fashion. It was effectively the product of a standards organisation, with a lot of smart minds spending time arguing about small details. For example, while JSR-37 (the original specification of the version of Java ME for mobile phones) was published in September 1999, it took until August 2002 for the specification for sending a text message to become available (JSR-120). The final result was typically elegant, consistent with overall Java ME design philosophy, and extensively documented. But you didn’t want to hold your breath for it.
I was developing to Android v2.2, which was the 8th release of the platform (not counting revisions). There had been five separate releases of the platform in the previous year (from the 3rd release in April 2009 to the 8th release in May 2010). It has been evolving very quickly, so I wasn’t too shocked to find things worked in unexpected ways.
I found the Android API library to be a bit confusing. Classes weren’t always in the packages that I expected to find them. For example, while Activity and Service are in android.app, ContentProvider and BroadcastReceiver are in android.content. Also, some UI elements are in android.view and others are in android.widget. And while some standard icons were available as constant values, others needed to be copied as files out of the SDK.
The Activity-oriented software architecture also took a while to get used to. It turned out that although one method I tried to use (startActivity) was available on some classes (such as a Service), they would throw an error if called because they were only meant to be called from particular components (an Activity, in this case).
Additionally, while ordinarily an application runs in a single process, it uses a number of threads. There is one special thread called the UI Thread. Again, one method that I tried to use (showDialog) was available in a class, but silently failed when it was called from a thread other than the UI Thread. In practice, you need to use an Android construct called a Handler to pass messages from one thread to another to allow the right thread to invoke the right method.
Also, seemingly harkening back to the days of Java ME, the media library seemed to have frustrating bugs. One API call I was expecting to use as documented (MediaPlayer.setDataSource) turned out not to work at all, and that I had to specify a FileDescriptor rather than a file path to load a media file. Also, another API (MediaPlayer.getCurrentPosition) returned completely erroneous values, and I had to develop a work-around. Thank goodness for StackOverflow in both these cases.
In the end, I got my little app working nicely. It was very satisfying to find that there was the ability to effectively add a new feature into my phone.
In that sense, Android gives user-developers a lot of power. And while I was expecting it to be a straightforward Java SE like development exercise, I discovered that it had a lot more in common with Java ME development. I had hoped that such platforms would easily attract the large pool of desktop developers, but it seems that there is still a mobile-specific learning curve that a developer will need to go through, and this will shrink the available pool of expert developers.
That said, I hope that Java developers will take a look at Android and see what kind of features they can innovate on top of it. As for myself, I hope to find the time for another hobby project again soon.