Your Plastic Pal Who's Fun to be With
Google's Android caused a minor stir when it launched a few weeks back — Java in flavour, but without a full compliment of recognised APIs to make it a bona fide Micro or Standard Edition. Reaction was predictably mixed, some saw Google's roll-your-own approach as a harmful splintering of the Java brand, others saw it as inevitable.
Android is Google's venture into the mobile device space, an Open Source platform using its own abstraction layer, the Dalvik Virtual Machine, sitting atop a Linux foundation. Applications are broken up into pages called activities, written in Java, compiled to bytecode and translated into a single APK (Android package) ready for the DVM.
From a UI point of view moving from activity to activity is a little like browsing the web, with the current 'page' dominating the display. The Android OS has a simple but effective mechanism for snapshoting and restoring activity states. A mail client can honour a web link by firing up a browser, the browser can follow a link into an IM client, the IM client may invoke a mapping application, with little consideration for memory constraints. The user can then backtrack down this 'trail of invocation', with each activity revived in its prior state. Forming applications with connected components like this is actively encouraged in Android, indeed some of the Google promotional material even goes as far as to describe apps as mash ups.
It's worth noting, not all activities need to be user-facing. Android allows activities to run silently in the background as services, or trigger on specific OS events.
Controversially, while Android includes many of the most familiar
java.* packages, it compliments them with its own
android.* hierarchy for working with the mobile device itself. This includes 2D and 3D graphics, telephony and network communications. The latter is particularly important as Android looks forward to a time when the mobile market will be supported by ubiquitous always-on internet connections. To that end functionality like XMPP (eXtensible Messaging and Presence Protocol), media playback and Google Maps are well supported.
So that, in a nutshell, is Google Android — but what is it like to develop for? I suppose the only way to find out is to write a simple application...
Writing a demo Minesweeper application
After downloading and unpacking the SDK, my first challenge was to figure out how to get it all working without Eclipse. This turned out to be actually remarkably simple — indeed so simple that I wondered why the documentation made such a big play of the Eclipse link.
Creating an application is as easy as calling the
activityCreator(.py) script/Python code (do I detect the hand of a certain Java Posse member?) This creates the necessary files and directories, including an Ant
build.xml file (which regrettably has hard coded paths, so you'll need to recreate this if you move your application between computers.) The
emulator application provides your device emulation, while calls to
adb install bin/WHATEVER.abk will squirt your current build onto the emulator where it can be tested.
adb is a general purpose debugging/shell utility — very handy if you want to probe around inside the device's file system or embedded SQL database. The
ddms application provides a remote window onto the activity of the emulator.
And so, after completing the tutorials, I decided to code something simple from scratch. I plumped for the classic desktop game Minesweeper. While it doesn't require any networking, it does provide a few user interface challenges, and leaves the door open to add features like a high score table which might employ Android's lightweight SQL database.
Resources and localisation
Developing activities in Android is divided between Java source code and XML resource files. The resource files allow strings, interface styling and other data to be specified outside of the source code. Living in their own subdirectories under res/, resource XML data is silently compiled into the APK and made available to the Java code via a special resource class. Crucially user interfaces can also be constructed using this XML format. These resource directories can be tied to different locales or different device profiles (eg: screen orientation) if desired. Android will transparently select the most appropriate set when your application runs.
As with Swing's Synth PLaF, it's possible to use either colours or bitmaps to define a component's look. Cunningly Android can use a 9 patch format for PNGs, utilising a border of pixels to specify how the image should be stretched and where its internal 'content area' should fall.
The idea is to define all user-facing components (UI, style, label text, graphics) in a format more closely resembling web markup. But the result is something, I suspect, neither desktop nor web developers will feel entirely familiar with.
One flaw I noticed is it doesn't seem possible to merge, concatenate or otherwise embed resource references...
android:label="@string/appName : @string/version">
It quickly becomes apparent the XML format has limitations. You still need to pull XML defined widgets back to the Java to assign event handlers, for example. But on the whole the XML resource idea seems to works fine, even if it took me a little while to get used to.
(Incidentally, resources is where I encountered my first Android bug — it seems whitespace is stripped from the ends of strings.)
User Interface layout and events
Android's user interface API is very different to both Swing and MIDP. Android uses layout containers, but fractured into two parts: the layout container itself and a corresponding
LayoutParams class which must be added to each child. Different layout containers demand different params.
AWT and Swing containers do not require this level co-operation with their children, as all data and methods relating to layout are neatly contained within the containers. I'm not sure I care for the way layout considerations 'bleed' down as they do in Android, requiring child components to be aware of their parent's requirements. It's a cyclic relationship which I assume is a side effect of Android's XML format, removing the need for param elements to wrap every child element, but instinctively (to my mind at least) it seems somehow wrong!
Android comes with a modest compliment of widgets: buttons, text boxes, etc. But it is clear that this initial release is far from complete. For example there doesn't appear to be a card layout for replacing sections of an interface dynamically (although there is a tab panel) and some of the layout classes didn't seem to size components correctly in all circumstances. I used an
android:layout_marginRight="10px" attribute, intending to introduce a small horizontal gap between labels and their components in a TableLayout, only to see the right hand column run off the edge of the screen by said ten pixels. Clearly TableRow doesn't yet factor in margins when it calculates layout.
These weren't the only UI woes I encountered. After using one of the standard in-built themes I discovered some of the colours were a little screwy. For example
Theme.Dark delivers white text on a light grey background for a highlighted Spinner component (Android's version of a combo-box.) It's annoying problems like this which can have you scratching your head for half an hour, before you realise it's not your fault.
Android's events are handled via a combination of old fashioned overridden methods (ala Java 1.02) and listener callbacks (ala Java 1.1). Listeners are added via a
setOn[Event]Listener call, which presumably means only one listener per component(?) Lifecycle type events relating to the current activity are best handled by overriding the corresponding
on[Event] method. This schizophrenic design can be a little confusing initially, but no doubt helps to keep down the number of anonymous inner classes.
Clearly my Minesweeper application didn't test the more powerful Android features. It was intended as only a basic trial of how the platform hangs together and how mature this initial release is. But the results were still rather impressive.
Yes the current SDK has a number of rough edges and gaps. For example I spent twenty minutes trying to understand why my application icons were all identical, until I realised icons sharing the same resource filename overwrite each other when the OS displays its application menu. But bugs can be fixed, and gaps easily plugged.
Although Android has some support for animated page transitions, it isn't in the same league as JavaFX Script when it comes to creating fluid user interfaces with ease. Where Android does score big is in the range of interaction it allows with the hardware. There's little feel of being trapped inside a applet container, shielding you from the actual OS/hardware. Instead the whole of the device, including such functionality as telephony and voice recognition, are laid open for you to use.
I think it's clear to see Android has a lot to offer the mobile Java market. It's a liberating experience for those of us used to the current JavaME. But politics cannot be entirely ignored: where will Android sit in the grand scheme of things? Is it forever to be shunned as a bootleg platform, or will it be blessed as one of the officially recognised Java editions?
In effect Android forces the community to confront a question it has long avoided: what exactly is Java? Just a language, or more than that?
Is Android 'Java'?