• Articles about computing
• Articles about software development
Mobile application development: Android compared to J2ME
Android is a Linux-based system developed by Google, and primarily aimed
at mobile handsets and other portable devices. Android provides a
Java-based development platform for applications which, like Apple,
it likes to call 'apps'. The ability to deploy applications written
in other languages remains uncertain, as does the suitability of
Android for devices much larger than a PDA. At the time of writing,
Android 2.2 is starting to appear on 10-inch Internet tablets, against
Google's opposition. Google claimst that Android
2.2 is completely unsuitable for tablets, which is probably true. Android
2.2 presents what is essentially a single-tasking user interface,
not very different in appearance from Qtopia or PalmOS.
There is no window manager or equivalent, and users do not (in principle)
control the lifecycle of applications. Each application's user interface
is sized to fit the screen, regardless of its contents.
Java 2 'Micro Edition' (J2ME) is a Java-based application platform for
mobile devices developed by Sun Microsystems, as it then was. Unlike
Android it is not a complete platform, just a virtual machine (VM). Device
vendors are, in principle, free to implement the J2ME VM however they
like. Some devices supporting J2ME are Linux based; many are not.
J2ME is actually a set of specifications, for platforms of varying
sophistication. In practice, most mobile phone handsets and PDAs have never
supported anything other than the pair of specifications called
'MIDP/CLDC' — the very bottom rung of the
J2ME ladder. If your cellphone is 'Java enabled', it almost certainly
supports the very limited MIDP API set. MIDP2.0 offers an advance on
the earlier 1.0 release, but both are very limited compared with
desktop Java platforms.
This makes J2ME of dubious value in modern, powerful handsets, which
typically have high storage capacity and high-resolution screens.
MIDP is really aimed at devices of the same vintage as the
Palm 3 PDA. In fact, the MIDP storage model is based on
'record stores' — a concept that maps exactly onto the PalmOS storage
In terms of positioning, the Android development model is more like the
J2ME 'Personal Profile', although it has similarities with MIDP2.0,
specifically in lifecycle management and media support.
Android Java has a fairly sophisticated (entirely
proprietary) user interface model, albeit still essentially single-tasking.
Programs are allowed to read and write files, open network connections to
arbitrary hosts, and manipulate the device hardware (subject to
certain security restrictions — see below). Significantly
for many applications, Android is not an integer-only plaform, as CLDC is.
The lack of floating-point support essentially precludes common J2ME
implementations being used
for scientific or mathematical applications.
So in many respects Android Java feels like a much more modern platform
than J2ME. However, PersonalJava and Jeode were offering a full Java
JVM for mobile devices more than ten years ago — it's perhaps
unfortunate that these Java implementations failed to address the
security concerns that made MIDP so much less worrying for device
vendors. If you think of Android Java as MIDP with a full Java API
and some hardware access, combined with a modern, declarative
user interface model, you won't be far off the mark.
Because MIDP2.0/CLDC is the dominant implementation of J2ME in the mobile
world, I won't be discussing any other flavours of J2ME in this article.
When I say 'J2ME', I mean the kind of Java implementation you're likely
to find on a Nokia or Sony-Ericsson phone handset, which will be
Java language issues
Both J2ME and Android Java applications are recognizable Java programs,
made from assemblies of Java classes packaged into archives. A Java
developer won't find any surprises in the language syntax or structure.
Both J2ME and Android development use the Sun (as it then was) Java compiler
tool to translate
source code into Java byte-code, although raw byte code has to be
transformed in both platforms (see below).
In both platforms, the standard API library
supplied with Sun's Java implementation is not used. Instead,
programs link against the more limited API libraries supplied with the
respective development packages. The Android Java API set is not
related to J2ME or to desktop Java, but is derived from
the open-source Harmony project.
Both J2ME and Android API sets include many of the
well-known utility classes in
java.util, such as
collections and text formatting. Neither contains any of the standard
desktop user interface classes (
java.awt), as might be
expected. Android contains a full implementation of
in double-precision floating-point. However, and a little oddly,
most (but not all) the proprietary Android APIs that use decimal numbers
float, not double. Presumably this is for efficiency purposes, but the
conversion between double and single-precision can cause a bit
of head-scratching. J2ME developers are spared this complication by the
simple expedient of leaving out floating-point support altogether.
The Android APIs include
java.sql, and there are JDBC
drivers for the built-in Sqlite database implementation. Surprisingly,
the Android APIs also include
javax.sql, leaving open
the possibility of pooled database connections to
remote servers. A Java crypo provider is also included, so you can
Unlike J2ME developers, who have to contend with only
two varieties of the MIDP API set — only one of which is in
routine use — at the time of writing there
are no less than ten Android API levels. Matching the
API level to a specific Android version number is itself non-trivial,
and it's very easy to write a program that will only run on a limited
range of hardware. With increased support for larger devices like
Internet tablets, this situation is unlikely to improve.
J2ME and Android Java are alike in that neither platform runs Java
bytecode directly. Both platforms require additional transformation
steps that are unnecessary with full-scale Java virtual machines.
In the case of J2ME, this process is called pre-verification.
Pre-verification encapsulates a number of steps that would ordinarily
be done at application load time, and so speeds up application
loading on low-power devices. However, the instruction set used in
J2ME byte-code is essentially the same as in desktop Java.
In contrast, Android's JVM implementation, called Dalvik, uses a
different instruction set from Sun's. Therefore a substantial
transformation has to be applied to the compiled Java byte-code. The
result is a 'DEX' file, which can contain the transformed versions of
In both J2ME and Android development, the compilation and transformation
steps are fiddly, and difficult to accomplish at all without the
use of vendor-supplied build and code management tools. More on this
specific issue later.
In summary, both Android Java and J2ME provide a programming language and
API set that will be familiar to Java developers of any background. However,
there are substantial omissions from the API sets in both cases, compared
to desktop Java, and compilation is only the first step in a more
complex build process.
User interface model
Both J2ME and Android provide a user interface model that is very different
from the more familiar AWT and Swing. However, although all the names are
different, the J2ME and Android user interfaces are conceptually very
similar. Knowing one, it's not difficult to use the other, provided you
have the API references to hand.
Both user interfaces are form-based, single-tasking,
A form is a collection of data entry elements that occupies the screen.
J2ME actually uses the term 'form', where Android prefers 'activity'.
Android forms are implicitly stacked — that is, when one form
(activity) invokes another, the invoked activity is considered to be
'on top', and the only way the user can navigate is up or down the
stack. J2ME applications are, in practice, very often stacked the same
way, but the implementation of the stack is left to the developer.
In both cases there will be a 'main' or 'home' form which starts the
application. In J2ME this is selected programmatically, in Android
in an XML file. In both cases, the active form (or activity) occupies
the whole of the accessible screen — there are no 'windows' in
the sense that a desktop programmer would understand the term.
Android activities are a bit more than simple forms — they are
self-contained units of interaction. There is a well-defined protocol
by which activities pass data from one to another, and the strict
encapsulation of activities means that an application can, in principle,
invoke activities from a
different application. An application that needed the user to end a
geographical location, for example, could invoke a particularly activity
in a mapping application to collect the data.
To relieve dependence on specific applications,
the cross-activity invocation protocol allows the target activity
to be specified in terms of a textual description, rather like a URI.
This is a very interesting concept, although it's not clear that
many developers have so far taken advantage of it.
Another rather peculiar consequence of the encapsulation of activities is
that, if a specific activity fails with an exception, it does not normally
cause the whole application to fail. Typically the user will see the
notorious 'Force close' dialog box, and then the faulty activity
will just be popped off the stack and the underlying one re-presented
as if nothing had happened. Whether this is a good thing or a bad one
is arguable. Although activities can, and will, invoke one another,
they are very loosely coupled, and this takes some getting
By single-tasking I mean that the user does not normally see more
than one form at a time, regardless of how many applications are running.
In fact, both J2ME and Android hide the concept of 'running' from the
user altogether. Applications are not supposed to provide the user
with a way to close them — the system is supposed to do this according
to resource demand. What this means is that when a user navigates away
from your application to a different one, the system may shut
down your application completely, and re-invoke it later. As a developer,
you don't really get much control over this process, and you're expected
to maintain your application's state so that it can be stopped and started
at will by the system without irritating the user. Both J2ME and Android
provide specific methods for applications to save their states, but the
developer has to remember to use them. In both Android and J2ME, the
developer must implement methods that the platform will call back on
when the application's lifecycle state changes.
Because the user interface is essentially single-tasking, the developer
does not have to worry very much about handling situations where part of an
application's screen is obscured by another application. If the application is
running, it is visible, and the whole screen must be drawn. Android takes this
you-own-the-screen concept to extremes. For example, if your application is
running and the user changes the screen orientation (by physically tilting the
device from portrait to landscape, for example), Android will shut your
activity down and re-start it with the new orientation.
Both J2ME and Android are layout-managed, meaning that the developer
specifies the relative positions and sizes of objects in the user interface,
and the user interface manager chooses the exact sizes and placement. This
process will be familiar to Java desktop developers and, indeed, to anybody
that has developed for Unix using any programming language. It's more of a
shift for Windows programmers, who have got used to specifying exact screen
Android's layout manager, while conceptually similar to J2ME's,
is quite a bit more flexible. This is only to be expected, as we've
moved to larger, higher-resolution screens. J2ME has essentially only
one, layout model — the screen is filled top-to-bottom in reading
direction. Android's model allows for nested layouts including
simple flows, tables, and relative-positioning (that is, specifying
that element X should be to the left (say) of Y and below Z).
Layout management is pretty essential for a platform where applications
have to be able to adjust to screens from
a phone LCD display to a widescreen monitor. However,
although if you're careful you'll get a workable user interface on
all platforms, most likely you won't get a perfect user interface on
any platform. It's surprising how easy it is for a screen layout that
looks aesthetically ideal on one handset to be ghastly on another.
Some compromises inevitably have to be made here. PalmOS developers had
an easy time, with a screen that was standardised at 240x320 pixels. For
better or worse, those days have gone. Both J2ME and Android developers
do have to be aware how the layout manager works, and how to use
it to get the best aesthetic compromise across a range of screen types.
The declarative user interface
Both J2ME and Android allow a user interface to be built up programatically.
The process will be a familiar one to anybody who has worked with modern
programming methods — the user interface consists of programming-language
objects, which are linked together via API calls to form an object hierarchy.
J2ME calls the user interface objects 'items', while Android prefers the
term 'views', but conceptually they are the same thing. Both user interface
models are, predictably, event-driven. This means that the application
makes method calls on UI objects to register interest in events generated
by those objects — button clicks, text changes, whatever.
Where Android is significantly more modern than J2ME is that its development
model favours declarative user interface specification, with the
layout specified in an XML file. This process
will be familiar (surprisingly familiar, I expect) to anybody who has
worked with GTK's declarative user interfaces, especially the Glade
toolkit. It's also not very different from the 'resource files' that
Windows developers will probably be familiar with.
Elements are nested in the XML file exactly as they will
be nested in the object hierarchy. This is a very convenient and
natural way to construct a user interface.
However, the link between the declarative user interface and the application
code is not particularly natural or visible. For most developers, this
link is hidden behind the platform vendor's software tools, and to
some extent it's only a problem if you want to use different tooling.
Nevertheless, idiomatic Android code does look
a bit odd to traditionalists. Consider this snippet of code, which attaches
an XML-based user interface specification to an activity:
public void onCreate(Bundle savedInstanceState)
R is not defined anywhere in the source code of this
activity class. Indeed, it is not defined anywhere in the application. The
R.layout.main links, in fact, to a file,
res/layout/main.xml. And the file must be called main.xml,
and it must be in the directory res/layout. At least, it must unless
you're willing to rewrite all the build tools. The implicit
filename-to-variable mapping also applies to links between XML
files. For example, you can include an image from a file into a specific
place in a form by referring to its filename, provided you use the
correct directory structure. In fact, you can include multiple versions
of the same image, to suit displays of different resolution, and the
system will take care of presenting the correct one.
It has to be stressed that this implicit use of filenames and a particular
directory model is a feature of the build tools supplied by Google, and
not necessarily of the Android platform itself. What's
going on behind the scenes
is that the tools are parsing the XML files and building Java byte-code
to implement the UI features. So, for example, all UI layout files end up
in a class called
R, whose static variables can be referenced
by the application. This is all very well, but the process creates at least
three complications for the developer.
First, in order to write idiomatic code, and refer to your user interface
R.layout.whatever, the build tools need to know
your user interface package name. The package name becomes an integral
part of the application structure. We can refer to
R is a class in the same package as the
Java class that uses it. Structuring a complex user interface into different
Java classes is not at all straightforward.
Second, Android development depends on knowing (and remembering) a whole
heap of naming and file layout conventions.
Third, the build process is
(as might be inferred from the above considerations) pretty complicated,
and not well-documented. You're more-or-less constrained to setting up
your project file structure in the Google-approved way, whether it fits
your code management and workflow practices or not. The 'Google way',
for example, favours including resources for platforms of different
capabilities (e.g., different image sizes) all in one file, and letting
the device decide at run-time what to use. But if you prefer to build different
versions of an executable for different platform classes, you're
going to be fighting the build process all the way. It's worth keeping in
mind that the approved target for all Android applications is the
Google Android Marketplace, and the build process is set up to create
applications compatible with that delivery model, for better or worse.
Security and sandbox
J2ME and Android both provide a 'sandbox' model of application execution,
which attempts to protect the system and other applications from
badly-behaved code. Java, being a system based on a virtual machine, is
well suited for such an execution model. J2ME — at least as it is
normally implemented — lacks a sophisticated model of application
permissions. Consequently, J2ME applications cannot normally read or
write files, or open network connections to arbitrary places. This
is one of the reasons, I suspect, why J2ME enjoyed a much greater
uptake than PersonalJava — mobile handset and PDA vendors simply did not want the hassle
and expense of supporting a truly open platform. In Android, Google has had
to make an uneasy compromise between providing a platform that will
support powerful, feature-rich applications, and a platform that
hardware vendors will feel safe providing to users.
One feature of this compromise is that Java applications run
under different user accounts in different operating system processes.
This allows a measure of sandboxing to be provided by the Linux
system itself. This still leaves the issue of access to hardware
and network resources. The approach Google has adopted is to force
applications to declare the access privileges they require. This
declaration is in the manifest file which also specifies the required
API level, etc. If an application tries to carry out an operation that
requires a specific privilege, and that privilege has not been declared,
then the operation will fail. A device is free to reject applications
that declare particular privileges, or give users the option to do so.
This is not by any means a perfect security model. For example,
privileges cannot be elevated at run-time. So if an application requires
access to, for example, GPS positioning, it must declare it, even if
the application may never use GPS, and the user's device may
not even support it. However, for all its limitations, it is a more open
development model that J2ME offers, and more open than many other
virtual-machine based environments (e.g., Adobe Flash).
Building and Packaging
Both J2ME and Android expect applications to be delivered in the
form of JAR (zip) archives. Android calls its archives 'APK' files,
but they're plain JARs and the contents are recognizable.
There is a particular defined layout within the archive for both
platforms — one that is understood by the vendor's development tools.
Manual or scripted packaging is just about possible using J2ME — the archive
well-defined and the only assembly step that is likely to be unfamiliar
is the pre-verification. Assembling an Android application without the
vendor's tools is less agreeably contemplated. Not only does the process
involve unfamiliar steps like DEX transformation, there is also
the conversion of
XML user interface definitions into byte-code to contend with.
The Android SDK includes a proprietary tool that will build a
directory structure and an Ant build script, given certain project
settings. Thereafter, you should only need to run Ant to build
everything up to date. When using this tool, you have to settle on,
among other things, package names for
your main components up front — they are exceptionally hard to
There is also an Android plug-in for the Eclipse IDE
tool, although I haven't used that and can't comment on it.
In practice, the Ant-based build system works pretty well, provided
that you do things the Google way. The directories in the generated
project have specific purposes, and you can't change the layout or,
in some cases, even add new directories, without upsetting things.
In addition, my experience has been that dependencies between the XML-based UI
files and the corresponding Java classes are not always managed very
well by the tool — the two sets of byte-code got out of sync,
leading to peculiar and unpredictable failures of the application.
I've found it necessary to do complete rebuilds more often than
should really be necessary. It's certainly worth doing this if
your application behaves bizarrely for no obvious reason.
Emulation and debugging
You can, of course, test J2ME and Android applications on a real device.
Or, better still, a number of real devices.
Methods for getting code onto a real device vary according to platform
and manufacturer. Most end users will user some sort of web-based
market to obtain their applications — Google offers the Android
Marketplace, although there are other sources. For J2ME, a whole range
of different market implementations are in use.
Because you won't (I presume)
want to go through a Web marketplace to test your own code,
you'll need to find a way to get the APK or JAR files onto the device, and in
practice most devices do not make this easy. You can in some cases
copy the archive onto the device over a USB connection, or through a memory
card, but that still leaves the problem of getting the device
to recongise it. A number of third-party file managers will launch the
package installer if pointed at an application archive. An alternative for
Android, albeit a
complicated one, is to use the Android Debug Bridge (ADB, supplied with the development kit) to push an APK over a USB connection.
It's difficult to give specific instructions about installing applications
either on Android or J2ME. Some Android devices do not even allow code
to be installed except via ADB or the marketplace. Some devices require
users specifically to configure the device to install these
One method of installation that does generally work is to put the
application on Web server, and point the device's Web (or WAP) browser at
it. This is fiddly to set up in the first instance but, once set up,
reasonably quick to use. Of course, it requires that you have access to
a Web server that the device can reach.
In practice, most developers prefer to test their code on an emulator of
some sort, not least because it makes it easier to collect debug output.
Emulators are supplied for J2ME and Android, but the implementations are
significantly different. At the time of writing, the only way to emulate
the Android Dalvik JVM is on a complete, machine-level implementation
of an Android handset. Google supplies such an implementation, which runs a
compiled ARM-CPU build of the Android platform on a complete ARM
platform emulator. On the one hand, this gives a highly realistic emulation — it's as near to running on a real device as you can get. On the other,
the emulation is slow and resource-intensive — superficially it's like
running Android Linux under a virtual machine on your development
workstation, but it's not a virtual machine in the way that, say,
VMWare is. The Android emulator uses QEMU to emulate the ARM CPU which,
of course, most likely is not what your development workstation has.
J2ME emulators tend to simple Java applications, that implement the
J2ME UI elements in Java code. This is much faster and lighter, but
arguably not as realistic. Work is underway to port the Dalvik JVM to
platforms other than Android, but that still leaves the problem of
emulating the Android user interface if you want to test Android code.
It seems that the Google full-emulation approach is likely to remain
the only show in town for now, aside from using a real device.
Developing for Android is both similar to, and different from,
developing for J2ME — and both are rather different from developing
desktop Java applications.
and J2ME applications are based on Java classes, using standard
Java syntax and a large subset of the Sun Java APIs. Both provide
a form-based, layout-managed, single-tasking user interface, based
on a hierarchy of objects. Both UI models are event-driven, and
have a lifecycle managed by the platform. Both platforms depend on
vendor-supplied development tools in addition to a Java compiler,
and both expect applications to be packaged up in particular
ways. Although Android and J2ME use different terms for almost
everything, concepts mostly map neatly between the platforms — the
developer merely has to learn an entire new vocabulary.
The most significant differences are around security and the use
of declarative user interfaces. Android applications may be
allowed access to files, hardware, and network connections, while
J2ME almost always prohibits this. The declarative user interface
tools are straightforward to use and effectively separate presentation
from logic. But they do impose workflow and file layout restrictions
on the developer which not everybody will be comfortable with.