BUY THIS BOOK
This print book is out of stock, with no immediate plans to reprint.

Safari Books Online

What is this?


Looking to Reprint this content?


J2ME in a Nutshell
J2ME in a Nutshell By Kim Topley
March 2002
Pages: 468

Cover | Table of Contents | Colophon


Table of Contents

Chapter 1: Introduction
This book is an introduction to and a quick reference for the Java 2 Micro Edition (J2ME) APIs. J2ME is a family of specifications that defines various downsized versions of the standard Java 2 platform; these downsized versions can be used to program consumer electronic devices ranging from cell phones to highly capable Personal Data Assistants (PDAs), smart phones, and set-top boxes. Diverse as they are in both form and function, these devices have in common the fact that they either do not have the memory and/or processing power or do not need to support J2SE, the standard Java platform used on desktop and server systems. This chapter introduces J2ME and compares it to other platforms that target the same range of hardware.
In the early 1990s, Sun Microsystems created a new programming language called Oak as part of a research project to build consumer electronics products that relied heavily on software. The first prototype for Oak was a portable home controller called Star7, a small handheld device with an LCD touchscreen and built-in wireless networking and infrared communications. It could be used as remote control for a television or VCR and as an electronic program guide, and it also had some of the functions that are now associated with PDAs, such as appointment scheduling. Software for this type of device needs to be extremely reliable and must not make excessive demands on memory or require an extremely powerful (and therefore expensive) processor. Oak was developed as a result of the development team's experiences with C++, which, despite having many powerful features, proved to be prone to programmer errors that affected software reliability. Oak was designed to remove or reduce the ability for programmers to create problems for themselves by detecting more errors at compile time and by removing some of the features of the C++ language (such as pointers and programmer-controlled memory management) that seemed to be most closely associated with the reliability problems. Unfortunately, the market for the type of devices that the new language was intended for did not develop as Sun hoped, and no Oak-based devices were ever sold to consumers. However, at around the same time, the beginnings of public awareness of the Internet created a market for Internet browsing software. In response to this, Sun renamed the Oak programming language Java and used it to build a cross-platform browser called HotJava. It also licensed Java to Netscape, which incorporated it into its own popular browser, at the time the undisputed market leader. Thus, the world was introduced to Java applets.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
What Is the J2ME Platform?
In the early 1990s, Sun Microsystems created a new programming language called Oak as part of a research project to build consumer electronics products that relied heavily on software. The first prototype for Oak was a portable home controller called Star7, a small handheld device with an LCD touchscreen and built-in wireless networking and infrared communications. It could be used as remote control for a television or VCR and as an electronic program guide, and it also had some of the functions that are now associated with PDAs, such as appointment scheduling. Software for this type of device needs to be extremely reliable and must not make excessive demands on memory or require an extremely powerful (and therefore expensive) processor. Oak was developed as a result of the development team's experiences with C++, which, despite having many powerful features, proved to be prone to programmer errors that affected software reliability. Oak was designed to remove or reduce the ability for programmers to create problems for themselves by detecting more errors at compile time and by removing some of the features of the C++ language (such as pointers and programmer-controlled memory management) that seemed to be most closely associated with the reliability problems. Unfortunately, the market for the type of devices that the new language was intended for did not develop as Sun hoped, and no Oak-based devices were ever sold to consumers. However, at around the same time, the beginnings of public awareness of the Internet created a market for Internet browsing software. In response to this, Sun renamed the Oak programming language Java and used it to build a cross-platform browser called HotJava. It also licensed Java to Netscape, which incorporated it into its own popular browser, at the time the undisputed market leader. Thus, the world was introduced to Java applets.
Within a couple of years, the cross-platform capabilities of the Java programming language and its potential as a development platform for free-standing applications that could be written once and then run on both Windows and Unix-based systems had sparked the interest of commercial end users as a way of reducing software development costs. In order to meet the needs of seasoned Windows and Motif/X-Windows developers working to create applications for sophisticated end users accustomed to using rich user interfaces, Sun rapidly expanded the scope (and size) of the Java platform. This expanded platform included a much more complex set of user interface libraries than those used to build the original applets, together with an array of features for distributed computing and improved security.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
J2ME Specifications
All of the J2ME configurations and profiles have been developed as part of the Java Community Process (JCP). The JCP brings together leading players in the relevant industries with the aim of agreeing on a common specification to which they can all design their products. Each configuration or profile started out as a Java Specification Request(JSR), which describes the scope of the work to be done and an outline of the areas to be covered. An expert group is assembled to create the specification, which is then subject to an internal ballot and revision before being made available for public review. Following public review and a possible last revision, the final draft is produced, and the JSR is completed.
The current list of JSRs, including those that have been completed, can be found on the JCP web site at http://jcp.org/jsr/all/. The JSRs that define the current J2ME configurations and profiles are as follows:
Number
Scope
JSR 30
J2ME Connected Limited Device Configuration (CLDC)
JSR 37
Mobile Information Device Profile for the J2ME Platform (MIDP)
JSR 75
PDA Profile for the J2ME Platform
JSR 36
J2ME Connected Device Configuration (CDC)
JSR 46
J2ME Foundation Profile
JSR 129
Personal Basis Profile Specification
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
J2ME and Other Java Platforms
J2ME is intended to be the way ahead for Java on small devices, but, as noted at the beginning of this chapter, there are other Java platforms already in existence (and in use) that have similar scope. The following sections briefly summarize these alternative platforms and compare them to J2ME.
JavaCard is a platform aimed at smart card technology. Smart cards are the smallest environment for which a Java platform exists. The constraints of these devices are such that the JavaCard virtual machine and the small set of Java class libraries that it supports require only around 16 KB of non-volatile memory and 512 bytes of volatile memory. The scope of J2ME does not extend to platforms with this little resource, so there is no J2ME configuration that is suitable for the current generation of smart cards. You can find more information about JavaCard at http://java.sun.com/products/javacard/.
EmbeddedJava is a JDK 1.1-based platform that is used to create software for embedded devices. These devices typically have a 32-bit processor with 512 KB of ROM and 512 KB of RAM available for the VM, class libraries, and embedded application. Since embedded devices generally serve only one purpose, it is unnecessary to include parts of the Java platform that the application does not require. In fact, EmbeddedJava allows the implementor to remove any package or class -- or even a method within a class -- that is not required, in order to fit the final product into the memory available. The EmbeddedJava specification, which can be found at http://java.sun.com/products/embeddedjava/, defines only the maximum possible content of the platform, rather than a minimum (as is the case with J2ME specifications).
EmbeddedJava is currently undergoing its end-of-life cycle, which means that it will no longer be supported as of January 1, 2003. In the future, developers in embedded environments will probably migrate to CDLC and one of its profiles, which are targeted to devices with similar resources.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: The Connected Limited Device Configuration
The Connected Limited Device Configuration (CLDC) is the basic building block on which the J2ME profiles for small devices, such as cell phones, pagers, and low-end PDAs, are built. These devices are characterized by their limited memory resources and processing power, which make it impossible for them to host a fully featured Java platform. CLDC specifies a minimal set of Java packages and classes and a reduced functionality Java virtual machine that can be implemented within the resource constraints imposed by such small devices.
The first part of this chapter describes the features that a Java virtual machine capable of supporting CLDC must provide, and it explains how such a VM differs from the standard one required by J2SE. As part of this discussion, we'll make use of Sun's reference implementation of the CLDC specification and the Kilobyte Virtual Machine, or KVM, around which it is based. The second part of the chapter covers the Java packages and classes that a CLDC implementation must provide, which are a small subset of the core packages found in J2SE. The chapter concludes with a discussion of the debugging facilities provided by the KVM and a couple of advanced features -- using native code and preloading Java classes -- that will be of interest to readers who want to work with the KVM at the source code level.
The hardware and software limitations imposed by the devices at which CLDC is targeted make it impractical to support either a full Java virtual machine or a complete set of J2SE core classes. Running a simple "Hello, world" application on the Windows platform requires around 16 MB of memory to be allocated. Contrast this with the minimum platform requirements for CLDC, which call for:
  • 128 KB of ROM, flash or battery-backed memory for persistent storage of the Java VM and the class libraries that make up the CLDC platform.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The CLDC Java Virtual Machine
The hardware and software limitations imposed by the devices at which CLDC is targeted make it impractical to support either a full Java virtual machine or a complete set of J2SE core classes. Running a simple "Hello, world" application on the Windows platform requires around 16 MB of memory to be allocated. Contrast this with the minimum platform requirements for CLDC, which call for:
  • 128 KB of ROM, flash or battery-backed memory for persistent storage of the Java VM and the class libraries that make up the CLDC platform.
  • 32 KB (or more) of volatile memory to be available for runtime allocation. This memory is used to satisfy the dynamic requirements of Java applications, which include class loading and the allocation of heap space for objects and the stack.
In order to support a Java runtime environment with such limited resources, CLDC defines reduced requirements for the virtual machine, the language itself, and the core libraries, details of which we'll describe in the following sections.
Other than the memory requirements, CLDC makes few assumptions about its host platform. It does not, for example, assume that the device will have any kind of display or user input mechanism such as a keyboard or a mouse, and it does not require any kind of local storage for application data. These issues are all assumed to be addressed individually by each device vendor. J2ME profiles, of course, place additional requirements that are suitable for the more limited range of devices they are intended for, as you'll see in Chapter 3 and Chapter 7. For CLDC, the number of requirements is minimized in order to maximize the number of platforms on which it can be implemented.
As far as the software environment is concerned, CLDC assumes only that the host device has some kind of operating system that can execute and manage the virtual machine. Although Java is a multithreaded programming environment, it is not necessary for the operating system to have the concept of threads or even to be able to schedule more than one process at any given time. Instead, the virtual machine is required to provide the illusion of a multithreaded environment using whatever native functionality is available to it.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The CLDC Class Libraries
CLDC addresses a wide range of platforms that do not have sufficient memory resources to support the full range of packages and classes provided by J2SE. Because CLDC is a configuration rather than a profile, it cannot have any optional features. Therefore, the packages and classes that it specifies must have a small enough footprint that they can be hosted by devices that meet only the minimum requirements of the CLDC specification. The CLDC class library is very small -- it is composed of a package containing functionality that is specific to J2ME (called javax.microedition.io), along with a selection of classes from the following packages in the core J2SE platform:
  • java.io
  • java.lang
  • java.util
All J2ME configurations and profiles include packages or classes from J2SE. When J2ME incorporates software interfaces from J2SE, it must follow several rules:
  • The names of the packages or classes must be the same, wherever possible. It would not be acceptable, for example, to completely reimplement the java.lang package in a package called javax.microedition.lang if the API in the java.lang package can be used.
  • The semantics of classes and methods that are carried over into J2ME must be identical to those with the same name in J2SE.
  • It is not possible to add public or protected fields or methods to a class that is shared between J2SE and J2ME.
Because of these rules, J2ME packages and classes will always be a subset of the packages and classes of the same name in J2SE, and the J2ME behavior will not be surprising to developers familiar with J2SE. Furthermore, J2ME configurations and profiles are not allowed to add extra functionality in packages and classes that they share with J2SE, so upward compatibility from J2ME to J2SE is preserved. However, it is permissible to exclude from J2ME those fields, methods, and classes that are deprecated in J2SE and this has been done by the Java Community Process expert group responsible for the CLDC specification.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
KVM Debugging
In order to provide Java-level debugging facilities, hooks must be supplied by the Java VM so that a debugger can perform tasks such as placing breakpoints, inspecting and modifying objects, and arranging to be notified when a debugging-related event occurs within the VM. The Java 2 platform includes an architecture, called the Java Platform Debugger Archicture (JPDA), that defines the debugging features that must be provided by a VM and the way in which they can be accessed by a debugger. Figure 2-1 shows the logical software components defined by the JPDA.
Figure 2-1: The Java 2 Platform Debugger Architecture
In the JPDA, the debugger interacts with the Java VM using a well-defined protocol called the Java Debug Wire Protocol (JDWP). This protocol specifies messages that are passed from a JDWP client to a JDWP server to request that operations be performed on the target VM, corresponding to debugging commands issued by the user. It also defines events that can be transmitted in the opposite direction to notify the debugger of state changes within the VM.
The architecture separates the debugger and the JVM from the details of the wire-level protocol by inserting an insulating layer on each side of the JDWP; this layer takes care of mapping the protocol messages to and from the programming interfaces required by the debugger and provided by the VM. In order to make it possible to accomodate different VM or debugger implementations without requiring each of them to provide their own JDWP implementation, two internal APIs are defined:
The Java Debug Interface (JDI)
The JDI is a Java-level interface that exposes the services of a JDWP client to a debugger. Typically, the debugger is a GUI program written by a third party vendor, but it could provide a command-line interface (such as that provided by the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Advanced KVM Topics
To close this chapter, we look at a couple of advanced techniques you can use with the KVM. If your focus is on developing applications for mass market wireless devices, the techniques shown in this section will be of little relevance, because they require you to be able to build your own copy of the VM from its source code and ship it along with your application. This is an option that is likely to be open to you only if you are using the KVM in a specialist application of some kind or if you are working for a device vendor incorporating the KVM into a new product.
In order to build the KVM, you need to download a copy of the CLDC reference implementation and acquire a suitable compiler and build tools. The details of the build process and the development tools with which it has been tested can be found in the KVM Porting Guide, which is one of documents included with the reference implementation. Since describing how to compile the VM is beyond the scope of this book, the rest of this section assumes you have set up an environment within which you can compile and link the VM using the Makefiles supplied by Sun.
In a J2SE system, the core class libraries are stored in the file rt.jar and are dynamically loaded and linked on demand from the point at which the VM starts up. This has two consequences, both of which are not ideal in the kind of limited-resource environment toward which the KVM is targeted:
  • The process of loading a class and locating and linking it to other classes that it depends upon takes a certain amount of time. This time is relatively small for each individual class, but it becomes noticable when a large number of classes have to be loaded at the same time, which is typically what happens when an application starts executing. This effect would be much worse on the processors that the KVM runs on. These processors are slower than those used in desktop systems, but they are used in devices, such as cell phones, where the user will probably be prepared to wait only a very short time between requesting a service and the service becoming available.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 3: The Mobile Information Device Profile and MIDlets
The Connected Limited Device Configuration provides the basis for running Java on devices that have insufficient resources to support a complete virtual machine together with a full version of the J2SE core packages. However, if you are an application developer, it is extremely unlikely that you will ever need to write software that works solely with the APIs provided by CLDC, because it contains nothing that allows for interaction with users, storage devices, or a network. CLDC is intended to be a base layer on top of which a range of profiles that provide the missing facilities can be provided, in a form suitable for the class of device for which each profile is designed. The Mobile Information Device Profile , or MIDP for short, is one such profile, intended for use on small footprint devices with a limited user interface in the form of a small screen with some kind of input capability. This chapter introduces MIDP; in the following two chapters, we'll look in more detail at how it supports user interfaces, networking, and persistent storage of information.
MIDP is a version of the Java platform based on CLDC and KVM that is aimed at small footprint devices, principally cell phones and two-way pagers. It is also suitable for running on PDAs, and an implementation is available for PalmOS Version 3.5 and higher. (In the longer term, it is intended that these devices use the PDA profile, which is also hosted by CLDC.) The MIDP specification was developed under the Java Community Process and is available for download from http://jcp.org/jsr/detail/37.jsp.
The logical position of MIDP within the software architecture of a device that implements it is shown in Figure 3-1. The software that implements MIDP runs in the KVM supplied by CLDC and provides additional services for the benefit of application code written using MIDP APIs. MIDP applications are called MIDlets . As Figure 3-1 shows, MIDlets can directly use both MIDP facilities and the APIs described in Chapter 2 that MIDP inherits from CLDC itself. MIDlets do not access the host platform's underlying operating system and cannot do so without becoming nonportable. Because the KVM does not support JNI, the only way for a MIDP application to access native platform facilities directly is by linking native code into a customized version of the virtual machine.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
MIDP Overview
MIDP is a version of the Java platform based on CLDC and KVM that is aimed at small footprint devices, principally cell phones and two-way pagers. It is also suitable for running on PDAs, and an implementation is available for PalmOS Version 3.5 and higher. (In the longer term, it is intended that these devices use the PDA profile, which is also hosted by CLDC.) The MIDP specification was developed under the Java Community Process and is available for download from http://jcp.org/jsr/detail/37.jsp.
The logical position of MIDP within the software architecture of a device that implements it is shown in Figure 3-1. The software that implements MIDP runs in the KVM supplied by CLDC and provides additional services for the benefit of application code written using MIDP APIs. MIDP applications are called MIDlets . As Figure 3-1 shows, MIDlets can directly use both MIDP facilities and the APIs described in Chapter 2 that MIDP inherits from CLDC itself. MIDlets do not access the host platform's underlying operating system and cannot do so without becoming nonportable. Because the KVM does not support JNI, the only way for a MIDP application to access native platform facilities directly is by linking native code into a customized version of the virtual machine.
Figure 3-1: The Mobile Information Device Profile
Sun provides a reference implementation of MIDP that can be used on Windows; the Wireless Toolkit, which contains versions of MIDP for Windows, Solaris and Linux; and a separate MIDP product for use on PalmOS-based PDAs. Device manufacturers typically use the Sun reference implementation as the basis for their own products. They usually integrate additional code as part of their MIDP implementation to provide management features such as installation, removal, and management of MIDlets that are not portable between devices and hence not part of the reference software. As shown in Figure 3-1, this code (labeled "OEM Code") may use some combination of MIDP and CLDC services and will also depend on the host platform's operating system. Some parts of the core MIDP software are themselves device-dependent and thus are also supplied by the manufacturer. These typically include parts of the networking support, the user interface components, and the code that provides persistent storage.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The MIDP Java Platform
The Java platform available to MIDlets is that provided by CLDC as described in Chapter 2, together with a collection of MIDP-specific packages arranged under the javax.microedition package hierarchy. The core libraries themselves are almost unaffected by the MIDP specification; the only change is the addition of the J2SE 1.3 timer facility in the java.util package, which will be covered in Section 3.5.4. The MIDP specification also places the following requirements on the core libraries:
  • Like applets, MIDlets are managed in an execution environment that is slightly different from that of a Java application. As you'll see shortly, the initial entry point to a MIDlet is not the main( ) method of its MIDlet class, and the MIDlet is not allowed to cause the termination of the Java VM. In order to enforce this restriction, the exit( ) methods in both the System and Runtime classes are required to throw a SecurityException if they are invoked.
  • In addition to the system properties defined by CLDC, MIDP devices must set the microedition.locale property to reflect the locale in which the device is operating. The locale names are formed in a slightly different way from those used by J2SE, because the language and country components are separated by a hyphen instead of an underscore character. A typical value for this property would be en-US on a MIDP device, whereas a J2SE developer would expect the locale name in the form en_US. Since both MIDP and CLDC provide almost no support for localization, however, the precise format of this property is of little direct interest to MIDlets. Instead, it is intended to be used when installing MIDlets from external sources, to allow the selection of a version of the MIDlet suitable for the device owner's locale. The property must therefore be properly interpreted by the agent (perhaps a servlet running in a web server) that supplies the software.
  • The system property
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
MIDlets and MIDlet Suites
Java applications that run on MIDP devices are known as MIDlets. A MIDlet consists of at least one Java class that must be derived from the MIDP-defined abstract class javax.microedition.midlet.MIDlet. MIDlets run in an execution environment within the Java VM that provides a well-defined lifecycle controlled via methods of the MIDlet class that each MIDlet must implement. A MIDlet can also use methods in the MIDlet class to obtain services from its environment, and it must use only the APIs defined in the MIDP specification if it is to be device-portable.
A group of related MIDlets may be collected into a MIDlet suite. All of the MIDlets in a suite are packaged and installed onto a device as a single entity, and they can be uninstalled and removed only as a group. The MIDlets in a suite share both static and runtime resources of their host environment, as follows:
  • At runtime, if the device supports concurrent running of more than one MIDlet, all active MIDlets from a MIDlet suite run in the same Java VM. All MIDlets in the same suite therefore share the same instances of all Java classes and other resources loaded into the Java VM. Among other things, this means that data can be shared between MIDlets, and the usual Java synchronization primitives can be used to protect against concurrent access not only within a single MIDlet, but also between concurrently executing MIDlets from the same suite.
  • Persistent storage on the device is managed at the MIDlet suite level. MIDlets can access their own persistent data and that of other MIDlets in the same suite. However, it is not possible for a MIDlet to gain access to persistent storage owned by another suite, because the naming mechanism used to identify the data implicitly includes the MIDlet suite. This is partly to avoid unintended name clashes between MIDlets obtained from unrelated sources, and partly as a security measure so that a MIDlet's data cannot be read or corrupted by malicious code imported from an unreliable source.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
MIDlet Execution Environment and Lifecycle
All MIDlets are derived from the abstract base class javax.microedition.midlet.MIDlet, which contains methods that the MIDP platform calls to control the MIDlet's lifecycle, as well as methods that the MIDlet itself can use to request a change in its state. A MIDlet must have a public default constructor (that is, a constructor that requires no arguments), which may be one supplied by the developer if there is any initialization to perform or, when there are no explicit constructors, the empty default constructor inserted by the Java compiler. This is what a skeleton MIDlet class might look like:
public class MyMIDlet extends MIDlet {

    // Optional constructor
    MyMIDlet( ) {
    }

    protected void startApp( ) throws MIDletStateChangedException {
    }

    protected void pauseApp( ) {
    }

    protected void destroyApp(boolean unconditional) 
                              throws MIDletStateChangedException {
    }
}
At any given time, a MIDlet is in one of three states: Paused, Active, or Destroyed. A state diagram that shows how these states are related and the legal state transitions is shown in Figure 3-4.
Figure 3-4: The lifecycle of a MIDlet
When a MIDlet is loaded, it is initially in the Paused state. The usual class and instance initialization is then performed -- that is, static initializers are called the first time the MIDlet class is loaded, all instance initializers are invoked when the MIDlet instance is created, and its public, no-argument constructor is then invoked. If the MIDlet throws an exception during the execution of its constructor, the MIDlet is destroyed. If the MIDlet does not throw an exception, it is scheduled for execution at some later time. Its state is changed from Paused to Active, and its startApp( ) method is called. The MIDlet class declares this method as follows:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Developing MIDlets
To illustrate the MIDlet lifecycle and how it can be controlled, we'll create a very simple MIDlet that does the following:
  • Prints a message when its constructor is called.
  • Creates a timer that fires from time to time, putting the MIDlet in the paused state if it is active and returning it to the active state if it is paused. When the timer has been through this cycle twice, it terminates the MIDlet.
  • Creates a background thread when it is started that simply prints a message every second. This thread is allowed to run only when the MIDlet is active.
Since you haven't yet seen how to create user interfaces, this example MIDlet communicates by writing messages to its standard output stream. On a real device, you can't see what is written to standard output or standard error (unless you are using debug facilities provided by the device vendor), but most device emulators provide a way to monitor the content of these streams. There are several products available that allow you to build and test MIDlets either in an emulated environment or on the real device; some of these products are described in Chapter 9. Here, we'll use the Wireless Toolkit, which is available free of charge from Sun.
The Wireless Toolkit provides an implementation of MIDP together with an emulator that can be customized to look and behave somewhat like a number of real cell phones. It can also be used in conjunction with a third-party emulator that allows you to see how your MIDlets would behave on handhelds that are based on PalmOS. It is not, however, a complete development enviroment, because it does not provide an integrated editor to allow you to create, view, and modify source code. Consequently, if you want to use the Wireless Toolkit as part of a complete development cycle, you will need a text editor or IDE to manage the source code. At the time of writing, the Wireless Toolkit can be installed to integrate with Forte for Java, which is available for download from Sun's web site, and Borland JBuilder, but any IDE will do.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Delivery and Installation of MIDlets
The MIDP specification creates the concept of a MIDlet, defines its lifecycle and its execution environment, and specifies the programming interfaces that a MIDlet can expect to be present on any conforming device. However, it currently does not address in any detail how the user should locate MIDlet suites, how MIDlet suites will be installed on a cell phone or a PDA, and what facilities are to be provided to allow the user to select and launch an installed MIDlet or to remove MIDlet suites from the device. These features are not covered in detail in the MIDP specification because they are largely device-specific. Instead, it refers loosely to software that is intended for application delivery and management. The term Application Management Software (AMS) is generally used to describe the software components that take on this responsibility. The MIDP reference implementation provides an example AMS for the benefit of vendors porting the software to their own devices, and both the Wireless Toolkit and the MIDP for PalmOS product have their own AMS implementations, which allow software to be installed from two different sources:
From a local host computer via a dedicated, relatively high speed connection
This mode of operation is particularly suitable for PDAs, which are typically associated with a desktop or laptop computer with which they periodically synchronize. Synchronizing backs up the user's data from the handheld onto the larger system and copies software and data in the other direction, as well. The MIDP for PalmOS implementation is a good example of this, because its AMS allows MIDlet suites to be installed from a host PC during the synchronization process. Once the MIDlets are installed, they can be launched on the PDA in the same way as its native applications. The same application management features are supported for MIDlets, so they appear to be almost the same as native applications.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 4: MIDlet User Interfaces
MIDlets are intended to be portable to a range of devices with widely varying input and display capabilities, ranging from the very small, mainly two-color screens and restricted keypads on pagers and cell phones to the larger, often multicolor displays and more sophisticated keyboards or handwriting recognizers available on PDAs. Creating a set of user interface components suitable for such a wide range of devices is not a simple task. One option available to the MIDP designers was to use a subset of the Abstract Windows Toolkit (AWT) or Swing components from J2SE. However, this is not really a viable solution. Resource constraints rule out the adoption of Swing, while the basic user interface model around which the AWT is based is far too complex to be used on small devices.
Both AWT and Swing are based on giving the developer maximum freedom to create a rich and complex GUI in a multiwindowed environment, in which the user might be interacting with several applications at the same time. By contrast, because of the limited screen size, cell phone users do not expect to be able to work with more than one window or even more than one MIDlet at any given time. Instead of trying to find a subset of the AWT that would be appropriate for this restricted environment, the MIDP expert group chose to introduce a much simpler set of components and a lighter, screen-based programming model. In this model, the MIDlet developer focuses more on the business logic of the application rather than on the minute details of the user interface itself. The result is a class library that is much smaller and easier to use and also less demanding of memory and processor resources than either Swing or AWT.
The price to be paid for this simplicity is that developers using this "high-level" API are much less able to control the exact look and feel of their MIDlets; the programming interface does not include features that would allow customization of colors, fonts, or even component layout. The high-level API is covered in the second half of this chapter, but it does not represent the entire scope of the MIDlet user interface support. Recognizing that some application types, such as games (which are likely to form a large part of the software market for cell phones) require a much greater level of control, MIDP also includes a "low-level" user interface API. This API gives the developer exactly the opposite of the high-level API, namely complete control over (a part of) the screen and access to the keypad and whatever pointing device might be available. The trade-off for this greater control is greater responsibility: using the low-level API means writing code to draw everything that appears on the user's screen and interpreting every input keystroke and pointer movement to decipher what the user wants to do. J2SE developers with experience creating custom components for AWT and Swing applications will probably feel very much at home with the low-level API, which is covered in the next chapter.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
User Interface Overview
The user interface model for MIDP devices is very simple. J2SE applications often consist of several simultaneously visible windows between which the user can move the input focus simply by clicking with the mouse. A MIDP device, on the other hand, is required to display only a single "window" at a time, and the ability to move from one window to another depends on whether the MIDlet developer includes UI components that allow the user to do so. Furthermore, if there is more than one MIDlet running in a device at the same time, only one of them can have access to the screen, and the device may or may not provide a way for the user to select which MIDlet should be given the screen at any particular time. The MIDlet user interface library, which is implemented in the javax.microedition.lcdui package, includes several classes that represent the device's screen and provide the basic top-level windows. Developers can use these as the basis for building form-based MIDlets or more graphically sophisticated MIDlets, such as games.
The Display class represents a logical device screen on which a MIDlet can display its user interface. Each MIDlet has access to a single instance of this class; you can obtain a reference to it by using the static getDisplay( ) method:
public static Display getDisplay(MIDlet midlet);
A MIDlet usually invokes getDisplay( ) when its startApp( ) method is called for the first time and then uses the returned Display object to display the first screen of its user interface. You can safely call this method at any time from the start of the initial invocation of the startApp( ) method, up to the time when the MIDlet returns from destroyApp( ) or notifyDestroyed( ), whichever happens first. Each MIDlet has its own, unique and dedicated instance of Display, so getDisplay( ) returns the same value every time it is called. A MIDlet will, therefore, usually save a reference to its Display object in an instance variable rather than repeatedly call
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The High-Level User Interface API
A MIDlet written using the high-level API typically consists of one or more screens built using the Form, List, or TextBox classes, together with a set of Commands that allow the user to tell the MIDlet what actions to perform and how to navigate from screen to screen. Let's start our examination of the high-level API by creating a simple MIDlet with a single screen containing a TextBox.
TextBox is a component used to display and modify text. Since it is derived from Screen, TextBox occupies the entire screen of the device and therefore can accomodate relatively large amounts of text spread over several lines. Most of the API provided by TextBox is identical to that of a similar component called TextField, which is covered in detail in Section 4.2.9, later in this chapter. In this example, we use only the features that TextBox inherits from Screen (and which are not available to TextField, because it is not derived from Screen). The code for this example is shown in Example 4-1.
Example 4-1. Creating and Using a TextBox
package ora.ch4;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.TextBox;
import javax.microedition.lcdui.TextField;
import javax.microedition.lcdui.Ticker;
import javax.microedition.midlet.MIDlet;

public class TextBoxMIDlet extends MIDlet {

    // Maximum size of the text in the TextBox
    private static final int MAX_TEXT_SIZE = 64;
    
    // The TextBox
    protected TextBox textBox;
    
    // The MIDlet's Display object
    protected Display display;
    
    // Flag indicating first call of startApp
    protected boolean started;
    
    protected void startApp( ) {
        if (!started) {
            // First time through - initialize  
            // Get the text to be displayed
            String str = null;
            try {
                InputStream is = getClass( ).getResourceAsStream(
                    "resources/text.txt");
                InputStreamReader r = new InputStreamReader(is);
                char[] buffer = new char[32];
                StringBuffer sb = new StringBuffer( );
                int count;
                while ((count = r.read(buffer, 0, buffer.length)) > -1) {
                    sb.append(buffer, 0, count);
                }
                str = sb.toString( );
            } catch (IOException ex) {
                str = "Failed to load text";
            }
            
            // Create the TextBox
            textBox = new TextBox("TextBox Example", str, 
                                MAX_TEXT_SIZE, TextField.ANY);
            
            // Create a ticker and install it
            Ticker ticker = new Ticker("This is a ticker...");
            textBox.setTicker(ticker);
            
            // Install the TextBox as the current screen
            display = Display.getDisplay(this);  
            display.setCurrent(textBox);

            started = true;
        }  
    }

    protected void pauseApp( ) {
    }

    protected void destroyApp(boolean unconditional) {
    }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 5: The Low-Level MIDlet User Interface API
The high-level API provides enough functionality for you to create, with relatively little effort, MIDlets with user interfaces that work unchanged across a wide range of devices. The price to be paid for this, however, is that you are restricted to using the components provided in the javax.microedition.lcdui package, and you have very little control over the appearance of your MIDlet.
The low-level API gives you almost exactly the opposite situation. To use it, you need to put much more effort into creating the user interface, but in return you get pixel-level access to the screen, you have control over colors (or shades of gray) and fonts; and you can respond directly to the user's key presses or pointer actions. This section takes a detailed look at the low-level API, which is useful for writing simple games or drawing charts. It may be used on its own or mixed with screens built using Form and the other classes covered in the previous chapter.
Canvas is the basic building block of the low-level API. Because it is derived directly from Displayable, it inherits the ability to have associated Commands, but it does not provide a title or the ability to contain other components. Canvas gives you direct access to the screen of a MIDP device, apart from the area used to draw Command buttons or labels, as shown in Figure 5-1. In the figure, the black area is the part of the screen occupied by the Canvas itself.
Figure 5-1: The Canvas class
Unlike the user interface components that we have seen so far, Canvas is an abstract class. To use Canvas, you have to subclass it and implement the paint method to draw whatever you want to appear on the screen. This method is called with a single argument, which is an instance of another low-level API class called Graphics. This class provides methods that allow you to draw lines, rectangles, and arcs, fill areas with a solid color, and render text onto the device's screen. The
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Canvas Class
Canvas is the basic building block of the low-level API. Because it is derived directly from Displayable, it inherits the ability to have associated Commands, but it does not provide a title or the ability to contain other components. Canvas gives you direct access to the screen of a MIDP device, apart from the area used to draw Command buttons or labels, as shown in Figure 5-1. In the figure, the black area is the part of the screen occupied by the Canvas itself.
Figure 5-1: The Canvas class
Unlike the user interface components that we have seen so far, Canvas is an abstract class. To use Canvas, you have to subclass it and implement the paint method to draw whatever you want to appear on the screen. This method is called with a single argument, which is an instance of another low-level API class called Graphics. This class provides methods that allow you to draw lines, rectangles, and arcs, fill areas with a solid color, and render text onto the device's screen. The Canvas class also has methods -- which you can override -- to receive notification of key presses and use of the pointer (on those devices that have one).
The low-level API is intended to give you much greater control over the screen and keypad of a MIDP device than the high-level API does. In doing so, however, it makes it more likely that you will inadvertently create a MIDlet that is device-dependent because it relies on the dimensions of the screen or on a feature that is not universally available. To make it easier to write code that adapts itself to its environment, the Canvas and Display classes provide methods, described in the following sections, to allow you to query the attributes that distinguish one device from another.

Section 5.1.1.1: Display methods

Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Painting and the Graphics Class
When the platform determines that the content of a Canvas needs to be drawn onto the screen, it calls the paint( ) method, which the MIDlet developer is required to implement:
protected void paint(Graphics g)
This method is called at the following times:
  • When the Canvas becomes visible as a result of the Display setCurrent( ) method being invoked
  • When some or all of the Canvas reappears after being partly or wholly obscured by an Alert or a system screen, such as a menu of Commands opened from a soft button
  • As a result of application code requesting that the screen be repainted following a change in the data that it is rendering
The Graphics object passed to the paint( ) method provides methods that allow graphics operations, such as line and text rendering and color filling, to be performed on its target. The target is either the screen itself or, in the case of a platform that supports double buffering, an off-screen image that will be copied to the screen when the paint( ) method returns. Implementing this method is the only way to get a Graphics object that can access the screen; unlike the J2SE Component class, Canvas does not have a getGraphics( ) method that can be used to get access on demand to the screen space that it occupies. Therefore, all screen updates must be performed in the paint( ) method. The MIDP specification prohibits holding a reference to the Graphics object passed to paint( ) for use elsewhere.
When the visibility of a Canvas changes, the following methods are called:
protected void showNotify( )
protected void hideNotify( )
The MIDP specification guarantees that the paint( ) method will not be invoked before showNotify( ) is called and, following return from hideNotify( )
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Graphics Attributes
The Graphics class provides operations that let you do the following:
  • Draw straight lines, arcs, and rectangles
  • Fill the space occupied by an arc or a rectangle
  • Render images
  • Draw text presented in the form of a String or as character data
All these operations use a coordinate system to indicate at least their starting point, and most of them also use one or more attributes of the Graphics object that act as implicit parameters. When the paint( ) method is called, the attributes of the Graphics object that is passed to it have well-defined values that can be modified if necessary. The attributes and their initial values are listed in Table 5-1. A more detailed description of each attribute and the way in which it is used are found in later sections.
Table 5-1: Graphics Attributes
Attribute
Use
Initial Value
Clip
The clip sets the region of the Canvas within which graphics operations have any effect. The clip is discussed in Section 5.7.
Depends on the reason paint( ) was invoked
Color
The color that will be used when drawing or filling shapes or rendering text. See Section 5.3.2 for further details.
Black
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Drawing Lines and Arcs
The Graphics class methods that let you draw straight lines, rectangles, and arcs are very similar to those available in J2SE. There are, of course, none of the advanced features provided by Java 2D. Even some of the more basic features, such as convenience methods that let you draw polygons and polylines, are missing, although some of them can easily be simulated.
The drawing primitives work by determining the set of pixels that will be affected and setting each of them to the value of the current color attribute as set by setColor( ) or setGrayScale( ). Because there is no support for transparency and color blending, no account is taken of the initial state of an affected pixel.
Perhaps surprisingly, no provision is made for an "exclusive-or" drawing mode, in which the new pixel value is combined with the existing one using a bitwise exclusive-or operation. This is not an issue, in practice, because MIDlets have access to a Graphics object only in the paint( ) method, when everything must be redrawn, whether it has moved or not. By contrast, it is possible in J2SE to get a Graphics object at any time, and, therefore, parts of the screen can be updated directly, without having to wait for the paint( ) method to be called.
The simplest shape you can draw on a Canvas is a straight line:
public void drawLine(int x1, int y1, int x2, int y2)
This method draws a line between the two pixels at (x1, y1) and (x2, y2</