Skip to main content

Going Mobile with Duke

September 13, 2004

{cs.r.title}

(Part one of a three-part series)










Contents
Java on the Small Device
A Closer Look at J2ME
Developing MIDlets Using the J2ME
Wireless Toolkit
Creating a Small Sample
Program
Compiling, Running, and Deploying
the Program
A Few Notes About Compatibility
Conclusion

Earlier this year, Sun announced that 250
million cellphones worldwide are using Java technology
. Taking into account
how the market for mobile consumer devices is expected to grow in the near future,
this number will increase significantly. From a developer's point of view, we
are talking about an enormous number of potential customers and users. So why
not have a look at how to write Java programs for these gadgets? This article
introduces key aspects of the Java 2 Platform, Micro Edition (J2ME), offers
an introduction to the J2ME Wireless Toolkit, and shows how to develop and deploy
a small sample application.

Java on the Small Device

In making a home for itself on cellphones, personal digital assistants
(PDAs), TV set-top boxes, and other consumer electronics devices, Java
finally fulfills one of its earliest design goals. When James Gosling
and his team designed and implemented Oak and the *7 device (which is
usually described as something between a remote control and a PDA) in
the early 1990s,
they were doing so to serve exactly these platforms. But at the time, the desired markets failed to materialize, so the team
concentrated on the Internet. Nonetheless, the original vision of a
programming language to create applications that can be shared among a
variety of platforms, embodied in the "write once run anywhere" paradigm,
has always remained.

Talking about consumer devices means talking about a very heterogeneous
set of gadgets. Since this diversity affects programming (as we will see soon),
let us have
a look at some of these devices first. Cellphones differ
in the size and number of
colors of their displays. Usually, they lack a proper keyboard and
other sophisticated input devices but provide (possibly intermittent)
network access. PDA-like gadgets, on the other hand, usually have
larger displays and offer physical or soft keyboards, or handwriting
recognition. They may provide network access, as well. Finally,
smartphones combine key characteristics of the traditional PDA and
cellphone designs. They all have in common:

  • Quite a limited amount of memory.
  • A microprocessor running at low speed.
  • Slow network connections (which may not be available all the time).

Other devices (for example, TV
set-top boxes), may be better equipped, running at a faster speed, or provide permanent (and faster)
network connections.
Still, they are beyond the capabilities of ordinary computers.
So, providing Java technology for consumer electronics or embedded devices
means covering a broad and very diverse range of hardware.
Generally, to be usable on such devices, programs need to be as lean as possible,
having a very small memory footprint.
This applies to user programs as well as runtime environments. Consequently,
one Java edition would never scale from mobile devices to high-end servers.
Sun acknowledged and solved this problem a few years ago when they
introduced three Java editions:

  • Java 2 Platform, Standard Edition (J2SE) provides
    everything needed for the development of desktops and server-based applications.
  • Java 2 Platform, Enterprise Edition (J2EE) defines the
    standard for the development of component-based, multi-tier enterprise applications.
  • Java 2 Platform, Micro Edition (J2ME) provides an
    application environment for consumer and embedded devices described above.

This article focuses on key aspects of J2ME technologies and explains
how to make use of them when writing programs for mobile devices. But I
would like to make you aware of the fact that Java has been present on mobile
devices prior to the introduction of J2ME. For example, the
Symbian Consortium included a JDK-1.1-based runtime environment in Epoc Release 5, an operating system that was used
in the Psion Series 5mx range of personal digital assistants. And Sun offered
PersonalJava (based on JDK 1.1), or pJava, which may be considered the predecessor
to J2ME. pJava is still present in several Symbian-OS-based smartphones today.

A Closer Look at J2ME

J2ME is not one downloadable product. Instead, it is a collection of technologies
and specifications that comprises a variety of so-called configurations, profiles,
and optional packages implementers can choose from and combine them to finally
build a Java runtime environment that closely fits the requirements of a
certain category of devices. This is because the
hardware in the scope of J2ME is, as we have seen in the previous section,
by far too diverse to be covered by a single
specification or a "one fits all" set of APIs.

Configurations provide the base functionality for a
particular range of devices with similar characteristics.
Generally, a configuration comprises a virtual machine and a minimal set of class
libraries. Today, there are two important configurations:

Profiles are combined with configurations to provide the runtime
environment for a device category. They include higher-level APIs; for example, to access
the user interface or to allow persistent storage on a gadget. The most important profile
today is called Mobile Information Device Profile (MIDP).

Finally, optional packages provide functionality that may not be
associated with specific profiles or configurations. For example, Bluetooth-based networking
support is implemented as an optional package.

Developing MIDlets Using the J2ME Wireless Toolkit

Configurations, profiles and, optional packages compose a
complete runtime environment. On mobile
phones, you will quite often find the Connected Limited Device Configuration
being combined with the Mobile Information Device Profile and accompanied by
some optional packages. To ease development for such devices,
Sun offers a development kit for MIDP/CLDC applications (MIDlets) called the
J2ME Wireless Toolkit.
It contains an emulator for various devices, documentation, tuning and
optimization features, and a set of examples. The toolkit can be integrated into
several IDEs or used as a standalone application. Users of NetBeans 3.6,
for example, may download it using the NetBeans Update Center, which provides a
particularly convenient integration into NetBeans.

Working with the J2ME Wireless Toolkit is based upon so-called
MIDlet suites, which are .jar files that contain one or more
MIDlets, a .jar manifest file,
and application-specific resources such as images and text.
The suite is accompanied by a Java Application Descriptor (JAD) file,
which is needed to deploy the MIDlet suite.
MIDlet classes make up the application, one of which must extend javax.microedition.midlet.MIDlet.
Important tasks involving MIDlet suites are:

  1. Create new suites.
  2. Edit classes of MIDlets.
  3. Build the MIDlets.
  4. Run the suite in one of the supplied emulators.
  5. Change their properties.

To create a new MIDlet suite, choose any of your
existing NetBeans projects or create a new one
using the Project Manager (I found it convenient to collect MIDlet suites
within one NetBeans project). Make sure the Project window is visible,
right click on the Project root, select Add New...
and MIDlet Suite (which becomes visible if you expand the MIDPnode).
In step 2 of the Wizard, you have to enter the name of your MIDlet suite to be created
(for example, MIDletExample). Step 3 is shown in Figure 1.

Figure 1. New MIDlet Suite Wizard - step 3 of 4
Figure 1. New MIDlet Suite Wizard, step 3 of 4 (click for full-size image)

We use the HelloMIDlet template, which provides a minimal but
fully functional MIDlet.
Once you have finished step 4 of the wizard, its source code will be
shown in the NetBeans editor, allowing you to modify it.
We will do so, adding some extra functionality by showing a nice Duke
picture and letting him ask for the user's name.

Creating a Small Sample Program

Have a look at the methods of the HelloMIDlet template. A MIDlet may enter several states,
which are reflected in the structure of the program.
After the user has launched a MIDlet on his phone,
startApp is called. If, for example, he answers an incoming call,
the MIDlet should be paused: the runtime environment calls the
pauseApp method. Finally, destroyApp
is used to quit the application. We will expand the demo by adding code to the
startApp and commandAction methods.

In MIDP applications, data is usually shown
and entered on Screens. Screen is the
common superclass of all high-level MIDP user interface classes.
The contents to be displayed and their interaction with the user are
defined by subclasses, such as TextBox or Form.
We remove the TextBox from the example and add Forms instead.
Forms may contain an arbitrary mixture of items, such as images, choice groups,
ticker tapes, or
(editable) text fields. Usually they are added to the Form using its
append methods; scrolling text is represented by the Ticker class,
which we'll use to show Duke's greeting. It is attached to the Form
with the setTicker method. Our little program consists of two screens,
referenced by firstScreen and secondScreen instance
variables. Both Forms are constructed
in startApp. Please note that screens can be assigned commands.
To invoke them, the user has to press certain keys of the device or select entries
from a menu. We use commands to navigate through screens and to quit the program. To see how this
works, please refer to the commandAction method.

The source code of our expanded version is shown below. A .zip
file
is also available, containing the source code, the image of Duke, and
everything needed to deploy the MIDlet suite to a portable device.

/*
* MIDletExampleMIDlet.java
*
* written Aug 2004 by Thomas Kuenneth
* mailto:thomas@moniundthomaskuenneth.de
*/

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.io.*;

/**
* This demo is based on the HelloMIDlet
* template. It shows
* a PNG image, some greeting message and
* asks the user to
* enter his/her name
*/
public class MIDletExampleMIDlet
                  extends MIDlet
  implements CommandListener {
   
    private Command enterCommand;
    private Command exitCommand;
    private Display display;
    private Form firstScreen;
    private Form secondScreen;
    private TextField textField;
    private StringItem stringItem;
   
    public MIDletExampleMIDlet() {
        display = Display.getDisplay(this);
        enterCommand = new Command("Enter",
                   Command.OK, 1);
        exitCommand = new Command("Exit",
                  Command.EXIT, 1);
    }
   
    /**
     * Start up the Hello MIDlet
     */
    public void startApp() {
        /*
         * we define how the first
* screen looks like
         */
        firstScreen = new Form("Hello !!!");
        try {
       Image duke = Image.createImage("/duke.png");
       firstScreen.append(duke);
        } catch (IOException e) {
        }
        Ticker t =
new Ticker("I am Duke. What is your name?");
        firstScreen.setTicker(t);
        textField = new TextField("Who are you?",
"", 20, TextField.ANY);
        firstScreen.append(textField);
        firstScreen.addCommand(enterCommand);
        firstScreen.addCommand(exitCommand);
        firstScreen.setCommandListener(this);
       
        /*
         * now we define the second screen
         */
     secondScreen = new Form("Nice to meet you!");
        stringItem =
new StringItem("You entered the following name",
                 "");
        secondScreen.append(stringItem);
        secondScreen.addCommand(enterCommand);
        secondScreen.addCommand(exitCommand);
        secondScreen.setCommandListener(this);
        display.setCurrent(firstScreen);
    }
   
    /**
     * Pause is a no-op since there are
     * no background activities or
     * record stores that need to be closed.
     */
    public void pauseApp() {
    }
   
    /**
     * Destroy must cleanup everything not handled
     * by the garbage collector.
     * In this case there is nothing to cleanup.
     */
    public void destroyApp(boolean unconditional){
    }
   
    /*
     * Respond to commands, including exit
     * On the exit command, cleanup and
     * notify that the MIDlet has been destroyed.
     */
    public void commandAction(Command c,
                              Displayable s) {
        if (c == exitCommand) {
            destroyApp(false);
            notifyDestroyed();
        }
        else if (c == enterCommand) {
            if (display.getCurrent()
         == firstScreen) {
                stringItem.setText(
textField.getString());
                display.setCurrent(secondScreen);
            }
            else {
                textField.setString("");
                display.setCurrent(firstScreen);
            }
        }
    }
   
}

Compiling, Running, and Deploying the Program

Having finished programming,
let's look at how to compile the suite and run it inside
of the emulator (which is part of the Wireless Toolkit). Figure 2 shows the use
of the Execute menu item, and Figure 3 shows the result on the emulator.

Figure 2
Figure 2. Compiling and executing MIDlet suites

Figure 3
Figure 3. Our sample MIDlet running in the default color phone

To see how Duke greets you on different devices,
select devices from the Emulator dropbox, shown in Figure 4. Please try the Qwerty Device,
which looks pretty cool.

Figure 4. Choosing the emulated device
Figure 4. Choosing the emulated device

The task of deploying a MIDlet suite to a specific mobile device is
done by application management software (AMS) that ships with,
or is part of, the gadget.
Generally, AMS controls all aspects of MIDlet installation, removal, and
maintenance. It retrieves all necessary information from
the MIDlet suite .jar file and the Java Application Descriptor (JAD) file.
You can modify the content of this file with the Edit suite
command from the suite context menu. JAD files contain key-value pairs
that describe the MIDlet suite to the AMS; for instance, mentioning
the configuration and profile and their version numbers. The contents of
other values are presented to the user by the AMS; for example, URLs that
provide further information to a MIDlet suite.

A Few Notes About Compatibility

Configurations and profiles have evolved since their introduction in 1999.
The first release (1.0) of the CLDC specification, as described in
JSR 30, is
followed by CLDC 1.1
(JSR 139), adding, for example, floating-point math and
weak references. The same is true for MIDP, whose first specification
(JSR 37)
received major enhancements (MIDP 2.0,
JSR 118) concerning user interface or
game and multimedia functionality, for instance.
The newer versions are of course backward-compatible, but if you choose to
make use of features introduced in more recent specifications, your application
will not run on PDAs or cellphones that implement 1.0 versions of the CLDC-MIPD stack.
The J2ME Wireless Toolkit can be configured to match miscellaneous combinations of
profiles, combinations, and optional packages. The MIDlet Project configuration can be
accessed from the Project menu.

Conclusion

The J2ME Wireless Toolkit is a key element in the development cycle of MIDP/CLDC applications.
Though it can be used as a standalone product, it is particularly convenient when combined
with a powerful IDE, such as NetBeans. This article introduced several facets of the
Java 2 Platform, Micro Edition
and provided an introduction to important topics of MIDlet programming.
We have examined a small yet fully functional sample application, which provides the
basis for further programming.

Resources

Thomas Kunneth works as a software architect at the German authorities, specializing in Java-based rich clients.
Related Topics >> Mobility   |   Programming   |