The Java 2 Micro Edition (J2ME) gives Java developers the opportunity to leverage their skills onto a wide variety of mobile devices. Of course, mobile devices are diverse in their capabilities and horsepower, but J2ME abstracts away these differences by defining configurations and profiles, which, when taken together, provide a complete platform and API for application development on a particular family of mobile devices.
The Connected Limited Device Configuration (CLDC) and Mobile Information Device Profile (MIDP) combine to support the majority of low-cost mobile devices in use today, such as PDAs, wireless phones, and two-way pagers. In this article, you'll get your feet wet with J2ME by building a small sample application.
For some additional information on the configurations and profiles available for J2ME, check out "Making sense of the J2ME alphabet soup."
Say Hello to J2ME
The process of actually building, installing, and running an MIDP application is significantly different from that used for a standard Java application. So to do justice to the topic, I'll dedicate a future article to it. For now, you'll have to be content to examine the structure of a sample application. I've placed the code for a typical "Hello World!" application, called HelloJ2ME, in Listing A. The results of running HelloJ2ME are shown in Figure A.
|Why, hello yourself!|
Not too impressive, I know, but good examples rarely are. As you can see, HelloJ2ME extends the base MIDP application MIDlet class and imports two package namespaces, javax.microedition.midlet and javax.microedition.lcdui. The former includes the application's base MIDlet class, while the latter provides a set of Swing-like GUI elements for use in the application.
The MIDlet class provides three abstract methods that are used by the device's application manager to communicate with the apps it runs. The startApp method is called immediately after the constructor and anytime an application is made active, not just when the application is initially launched. An application may transition between active and inactive states multiple times during a single run, so you should avoid placing single-use initialization code here, such as code to initialize the UI, since it will likely be executed a number of times. Use the constructor for this purpose instead.
The destroyApp method is called by the manager to indicate that an application is about to be shut down. Unlike startApp, this method will be called only once during an application's lifetime, so it's safe to place cleanup code here. In fact, because the MIDP doesn't include finalize functionality for objects, you'll have to perform cleanup here. At the same time, though, a typical mobile device is much less stable than your typical standard platform and will be routinely powered off or reset by the user. So you can't really count on destroyApp being executed either.
The remaining abstract method, pauseApp, is a little weird at first blush. It's meant to provide notification that the app is about to be paused because the user has switched to a different application or is using a function of the device that will prevent the app from continuing to run. Because most mobile devices lack the horsepower to be truly multitasking, this will probably happen to your app a lot. You should also be a good citizen and free any resources you can inside this method. When the application is resumed, the startApp method will be called by the application manager.
Communicating with the application manager
Of course, communication has to be a two-way street to be effective, and MIDP applications are no exception. MIDlet provides a set of final methods you can use to communicate with the application manager:
- · NotifyDestroyed tells the manager that your app wants to be shut down. Calling this method will not result in your destroyApp method being executed, so you'll have to call it manually.
- · NotifyPaused notifies the manager that your app wants to be paused.
- · ResumeRequest asks the application manager to resume your app if it has been paused.
- · GetAppProperty retrieves configuration information about an app from a manifest or an application descriptor file, something I'll discuss further in a future article. For now, it'll suffice to think of this method as accessing a private initialization file.
Managing the interface
As I mentioned before, the javax.microedition.lcdui package contains the UI elements used with MIDP applications. Most of the UI elements you'll find here have analogous Swing counterparts, although the names are different, and the underlying event system works in essentially the same way for both APIs. You'll still be registering event listener objects with controls, as I do in HelloJ2ME's constructor. In this case, for simplicity, HelloJ2ME implements the commandListener interface itself and serves as the listener object for the sole Command object it contains. However, other techniques for creating event listener classes, anonymous inner classes, and dedicated classes will work just as well.
Meet the family
There are basically three families of GUI components defined in the lcdui package, which I group based on their base classes: Screen components, Item components, and what I'll call Miscellaneous Displayable components.
Screen components descend from the abstract class Screen and provide the traditional window-like GUI widgets. The Form object used in HelloJ2ME is a Screen descendant that can contain and display GUI controls. Other Screen components include Alert, a dialog box; List, which displays groups of choices; and TextBox, a multiline text-entry screen.
Item components are the traditional controls, like the "Hello World!" TextField in the sample app, that all descend from the Item abstract class, which provides a uniform API for labeling, event handling, and displaying controls. ChoiceGroup, DateField, Gauge, ImageItem, and StringItem are other Item components.
Miscellaneous Displayable components
Miscellaneous Displayable components all either descend from the higher-level abstract Displayable class or are in some way related to it. This group includes components like Command, a command button; Ticker, which displays scrolling text; Graphics, for displaying graphics; and Choice, an interface for manipulating predefined selections, which don't really fit in another category.
Figure B illustrates the hierarchical arrangement of these components.
|The denizens of the lcdui package|
The whole graphical shebang is managed by a Display object, of which each application has access to a single, private instance. This instance is retrievable via the static Display.getDisplay method, and it's customary to hold a single reference to this instance in a member variable, as HelloJ2ME does in its constructor. In addition to methods for setting the focus to a particular screen element (setCurrent) and retrieving the element with the focus (getCurrent), Display also exposes a handful of methods useful for obtaining information about the display capabilities of the device, notably whether color is displayed (isColor) and how many colors are supported (numColors).
Things to remember
I'll leave you now with a short list of things to keep in mind when developing Java applications for a mobile platform. First, you'll be dealing with an abbreviated class library: no reflection, JNI, or, as I mentioned, finalization support. Second, you'll be dealing with rather draconian memory restrictions, as most devices running the MIDP profile will have less than 100 K of dynamic memory available. As a result, you'll need to keep a wary eye on the memory use of any algorithms you employ. Finally, keep in mind that any network connectivity will be limited in bandwidth and probably sporadic.