For Java technology to fulfill its promise, it should be possible to test a Java application on just one device and, if it works properly, assume that it will run well on any other.
J2ME, in its most familiar guise of MIDP, comes closer to this ideal than either the Standard or Enterprise edition because there's only one version of the specification. Although there are different implementations, as far as the Java application is concerned it isn't able to tell which platform it's running on. There is a fly in the ointment, however. While MIDP offers a highly consistent runtime environment and so consistency of functionality, user interfaces vary wildly.
Meanwhile, on Planet Earth...
Real-world marketing issues mean that manufacturers produce phones in a range of shapes and sizes, with capabilities to suit every pocket. Can developers be blamed for wanting to take full advantage of the facilities of each individual device? Instead of forcing owners of high-end devices to make do with the minimal interface the J2ME standard requires, developers would, for instance, like to make full use of the large, deep-color screens that the latest devices sport.
Yet network operators (who aim to be the premier suppliers of mobile applications and services) don't just want portability; they demand it. They will, for many consumers, also be the first point of contact when technical problems arise. If a MIDlet behaves very differently across various devices, the technical support costs for the operator could spiral out of control, and these costs subsequently will have to be passed on to the consumer, the developer, or possibly both.
Obviously then, it's in the software developer's interest to minimize portability issues as much as possible.
The assumptions that MIDlet authors can make about the device running their applications are deliberately limited, and they have no control over application appearance. They do know, however, that their applications might be deployed on a device with only a numeric keyboard, a 96 x 54 pixel, and a 1-bit deep screen; or they might be deployed on a device with a _ VGA display, qwerty keyboard, and touch screen. Or anything in between. This has led to several different application styles.
The first style collects raw input events and uses Graphics, with its 2D primitives, directly for the UI. This style is typical of the games that currently form the bulk of available MIDlets and is aimed at smartphones. With these applications, assumptions about screen size, aspect ratio, and color depth are crucial factors when producing a portable app. These applications can be memory- and processor-hungry.
The second style of MIDP application uses displayables and commands to build simple form-based UIs, most similar to those on old green-screen mainframe apps. The commands are presented to the user in the same way that commands are usually displayed on the device. In principle, this offers the highest level of portability, since the items in the UI, and the commands that affect them, are presented to the user using implementations native to each device. As we shall see, there are problems with this approach.
A third style combines the first two approaches using a library such as kAWT to provide something closer to a traditional UI, with stronger layout control and richer UI components. This allows a great deal of portability at the expense of increased memory consumption and extra processor load. Application designers still need to make some assumptions regarding screen size.
All for One, and One for All...
To be allowed to bear the distinctive Java logo and use the phrase "Java powered," a device has to pass the tests in the Technology Compatibility Kit (TCK) from Sun Microsystems. There's just one TCK for all devices. This guarantees conformity to the Java standard.
However, the standard enforced by the TCK guarantees only the lowest common denominator, and it's possible for a MIDP implementation to pass the TCK tests and not perform well at all: in particular, the TCK has nothing to say about how UI components appear on screen, or how user actions are transmitted to applications.
The TCK also allows a great deal of latitude in how applications are deployed and managed, and an additional problem is that despite the presence of device emulators, these PC-based emulators often perform differently from their real-world counterparts - especially if the actual phone is still in development.
Table 1 shows the kind of differences that can be expected between various MIDP platforms.
Let's examine some of the more serious differences. First, two issues about the environments into which MIDlets are deployed.
The J2ME specification states that a MIDlet may pass through three stages during its life, from creation in the PAUSED state, through the ACTIVE state, to the DESTROYED state. The MIDlet class constructor can allocate any resources used only by the MIDlet, and startApp() can allocate "shared resources," which should be released when the MIDlet is paused. Nonshared resources must be released by destroyApp(). The intention here is that MIDlets PAUSED by the device's operating system must release expensive or volatile resources. This facility is meant to be used when a MIDlet is moved to the background on a task-swap.
Unfortunately, platforms differ in their interpretation of this feature. Some platforms, in fact, call destroyApp() when the MIDlet goes to the background, and create a new instance when it returns to the foreground. Clearly, a MIDlet that expects to be PAUSED but not DESTROYED could malfunction severely when restarted.
Rejecting Installation Files
J2ME, like the Standard and Enterprise Editions, uses Unicode characters. Some platforms on which J2ME is installed do not. This results in some platforms rejecting application descriptors that, quite validly, contain characters outside of the 7-bit ASCII character set (for instance, ä).
It can be worse than that. Some MIDP-enabled devices do not install from .jar and .jad files, but from proprietary binary formats created from the .jar and .jad files (one example is the RIM BlackBerry). Some MIDlets can't be directly translated into RIM .cod files because attributes in the .jad contain ASCII characters that are not valid in a project name in the RIM tool used to build .cod files.
Commands attached to a displayable will be presented to the user in the same way as commands that are part of the device's own UI are presented. This can cause confusion, since some platforms present commands in a menu that contains default items such as "select" and "exit". Some platforms present the commands in an immediate mode: simply selecting the command item sends an event to the application. On other platforms, a two-stage process takes place where the command is selected from a menu, then activated.
There are two problems here. Again, it's challenging to write user instructions that will make sense on every platform. Also, words belonging to a screen navigation metaphor, such as "select" and "back", should be avoided as names of commands. To a greater or lesser extent, the MIDlet's UI is presented within the context of the platform's own.
Trouble with Gauges
The gauge item illustrates some of the issues in UI appearance and interaction that occur with J2ME applications. On some platforms, the gauge item does not have a border, nor does it have any textual representation of the current value. So a gauge showing a value of 0 is invisible, merely a blank area on the screen.
On some platforms, a gauge item has accompanying text to indicate the current value, as well as the graphical display. On other platforms, this text displays the current value of the gauge and, still on others, it's the current value, as a percentage of the maximum value, that's displayed.
This uncertainty causes difficulties in writing portable applications using gauges, especially interactive gauges. Imagine also the difficulty in writing the user guide for an application using gauges, not knowing how the platform will display the gauge or its current value.
Figure 1 shows a form with a gauge, as implemented on Sun's reference platform. Figures 2, 3, and 4 show the same displayable from the MIDlet in the same state, but on three different platform-specific emulators. Notice that the reference implementation does not display any of the numerical parameters of the gauge, and neither does the platform in Figure 2, whereas the platform in Figure 3 shows all three parameters.
The platform in Figure 2 does display the title of the form being displayed ("Gauge: value 2") and displays both commands attached to the form ("back" and "continue"); the platform in Figure 3 does not display the form's title and displays only one command ("back"). The command "continue" is on the options menu, along with platform-supplied commands "copy text", "find in page", and "exit"". Both platforms indicate that the gauge has focus, by the ears shown on either side of it (see Figure 2), and the grey box surrounding it (see Figure 1).
On the reference implementation, it's the small arrows at the bottom of the screen that indicate that the gauge may be modified.
Contrast this with the platform shown in Figure 4. Here, the gauge shows the current and the maximum value (but not the minimum), and doesn't look much like a gauge at all. The gauge has focus, but in order to change the value, the "Edit" command must be chosen from the "Options" menu (see Figure 5) bringing the user to the gauge edit screen (see Figure 6). Clearly, any MIDlet will have very different usability on these three devices, but the one using gauges will provide spectacularly different user experiences.
Write Once, Run Everywhere
MIDP offers a highly uniform runtime environment across a wide range of mobile devices. However, differences between implementations mean that only the most trivial MIDlet is going to look the same on every platform.
As MIDP is deployed on more devices and a greater range of devices, from limited smartphones to powerful communicators, the true portability problem within J2ME - obtaining a consistent and consistently usable UI - will become ever greater. No two MIDP platforms, even from the same vendor, have exactly the same look and feel, so no MIDlet is ever going to have exactly the same user interface on every platform.
The most important MIDlet portability technique is to give up almost all the notions about user interface design that are so important in designing desktop or Web applications, and instead focus on giving your MIDlets as simple and small a set of user interactions as possible (with no assumptions made about appearance).
Emulators for all J2ME-enabled devices are available for (usually) little cost, so it's quite possible to exercise a MIDlet on many different platforms. This should be done by any developer who is truly serious about portability. Source code for this article can be downloaded from below.
* * *
White papers on the issues raised in this article are available from the Penrillian Web site, www.penrillian.com.
Jeremy Wakefield is a design consultant specializing in UI design and audio software. He was head of product software for Psion and later a design manager for Symbian.
Keith Braithwaite is technical lead for mobile software projects at Penrillian. He focuses on Java and C++ development with an emphasis on design, quality, and process. He is an active member of the XP community.
Tony Robinson is project manager at Penrillian with over 5 years of experience delivering tools, components, and frameworks for mobile platforms.