by Jonathan Knudsen
November 2002
Download: [source code]
Links: JSR 118: MIDP 2.0, J2ME Wireless Toolkit 2.0
Version 1.0 of the Mobile Information Device Profile (MIDP)
provides a standard API for application development. It includes APIs
for application lifecycle, HTTP network connectivity, user interface, and
persistent storage. MIDP 2.0 includes many enhancements and additions.
Most of the action is in the user interface packages, but the enhancements
are broad and comprehensive. Wireless Java developers have a lot to be
happy about.
This article provides a quick overview of the new features in MIDP 2.0. It is
organized as follows:
To install the example code, download the
source code archive and unzip it so the New20 directory
goes under the J2ME Wireless Toolkit's apps directory, like this:
<j2mewtk>/apps/New20
You may then open, build, and run the New20 project from the J2ME Wireless
Toolkit.
|
Schedule
Although the MIDP 2.0 specification and tools are available in the near term, it
will be some months before MIDP 2.0 handsets will be available in volume. The
process works this way:
- The specification becomes final after a public review. (As I write this, the
specification is "Proposed Final".)
- The reference implementation and Technology Compatibility Kit are released.
- Device manufacturers implement MIDP 2.0.
- Device manufacturers seek device approval from government regulators.
- Devices are released.
Current estimates are that MIDP 2.0 devices will be available
in large volumes in Summer 2003.
Secure Networking
The only network protocol the MIDP 1.0 specification requires is HTTP. MIDP
2.0 also requires HTTPS, which is basically HTTP over the Secure Sockets
Layer (SSL). SSL is a socket protocol that encrypts data sent
over the network and provides authentication for the socket endpoints.
Although many MIDP 1.0 implementations support HTTPS, application developers
cannot rely on its availability. MIDP 2.0 provides a stable, consistent
foundation for
wireless applications that deal with money or sensitive information.
HTTPS support is provided through the CLDC's Generic Connection Framework in the
javax.microedition.io package. Here's how you obtain a regular HTTP
connection:
String url = "http://www.cert.org/";
HttpConnection hc = null;
hc = (HttpConnection)Connector.open(url);
|
In MIDP 2.0, it's just as easy to make an HTTPS connection:
String url = "https://www.cert.org/";
HttpsConnection hc = null;
hc = (HttpsConnection)Connector.open(url);
|
javax.microedition.io.HttpsConnection is only one of several new
interfaces that
support secure networking. MIDP 2.0 also includes
javax.microedition.io.SecurityInfo, which contains information
about a secure connection, and javax.microedition.pki.Certificate,
which represents a cryptographic certificate.
The HttpsExample MIDlet in the source
code bundle for this article is a complete running example that
demonstrates retrieving security information from an
HttpsConnection.
To install the source code bundle in the J2ME Wireless Toolkit 2.0 directory
structure, just unzip the source code ZIP file.
Move the unzipped New20 directory under the apps
directory of the wireless toolkit installation. You can then open the project
using the wireless toolkit to build it and run it.
Multimedia
One of the most exciting aspects of MIDP 2.0 is its set of media APIs. These APIs are
an audio-only subset of the
Mobile Media API
(MMAPI). (For more information on the MMAPI, see
Mobile
Media API Overview).
The simplest foray you can make into multimedia is
to generate simple tones using the
playTone() method in javax.microedition.media.Manager.
All you have to do is supply a note number (60 is middle C), a duration (in
milliseconds), and a volume (0 is silent, 100 is loudest). This method throws a
MediaException if the tone cannot be played. The following code
plays middle C for half a second at the loudest volume.
try {
Manager.playTone(60, 500, 100);
}
catch (MediaException me) {
// Handle the exception.
}
|
The ToneExample MIDlet in the source
code bundle provides a simple form interface that allows
you to play different tones.
The API also supports playing sequences of tones. You'll need to dive
a little deeper and use the
javax.microedition.medi.control.ToneControl interface. The API
documentation for ToneControl has a simple example that illustrates
this technique.
Finally, MIDP 2.0's media APIs support playback of sampled audio.
Implementations must be able to play WAV files and
are free to support additional audio formats.
The code to play audio is surprisingly simple. First you obtain a
Player implementation for your audio data; then you set the
Player running. The following code demonstrates how to play a WAV
file stored as a MIDlet resource:
InputStream in =
getClass().getResourceAsStream("/signs_m.wav");
Player p = Manager.createPlayer(in, "audio/x-wav");
p.start();
|
(See the AudioExample MIDlet in the source
code bundle for this article.)
Form Enhancements
Various goodies have been added to the javax.microedition.lcdui
APIs in MIDP 2.0, but the largest changes (excluding the game APIs, discussed
later) are in Form and the Item family.
First, form layout is considerably more sophisticated than it was in
MIDP 1.0. The API documentation for Form describes the
new layout algorithm in detail.
Stated briefly, items are laid out left
to right in rows that stack from top to bottom, just like ordinary text. You can
modify this layout, but keep in mind that your application only requests
behavior from the implementation. In the end, it's the implementation that
decides exactly where the items go and how big they are.
Items now have a minimum size and a preferred size that can be
set by the application. If you don't specify these sizes the implementation
computes them. The Item class also includes layout
constants that previously were present only in the ImageItem
class. You can specify a horiztonal layout, a vertical layout, newlines before
or after an item, and other constraints.
Besides the new layout features, the available toolbox of form
Items has been expanded. New
in MIDP 2.0 is Spacer, a non-navigable
Item that represents empty space. You can use it to
fine-tune form layout. Next, the ChoiceGroup item has a new
type, POPUP. A POPUP ChoiceGroup is
essentially a combo box. It shows a current selection and some visual cue (a
triangle pointing down, for instance) to
indicate that there are more options. Select or activate it and the whole list
of choices pops up, ready for a new selection.
MIDP 2.0 also extends command handling. In MIDP 1.0,
Commands are added to Displayables and a single
listener object receives all command events. MIDP 2.0 extends this model by
allowing you to add Commands to individual Items.
From the application programmer's point of view, this added flexibility
is very easy to
understand. The implementation has a somewhat harder job of figuring out how to
show commands appropriately. The programming paradigm is very similar to adding
Commands to a Displayable. Just pass a command to the
Item's addItemCommand() method. To register a
listener, implement the ItemCommandListener interface and register
the listener with Item's setItemCommandListener()
method.
Items also have a default command, a command that can be
invoked using a particular user interface gesture. This varies from device to
device; it could be a special button or a stylus gesture. You can set a default
command with Item's setDefaultCommand() method.
The big new fish in Form's waters is CustomItem, a
class that allows you to create your own Items. Similar
conceptually to a Canvas, CustomItem allows you to do
your own drawing and to respond to user interface events. Creating a custom
item is
a matter of subclassing CustomItem and implementing its abstract
methods. The following example is essentially a toggle button with a hardcoded
minimum size.
import javax.microedition.lcdui.*;
public class DiamondItem
extends CustomItem {
private boolean mState;
public DiamondItem(String title) {
super(title);
mState = false;
}
public void toggle() {
mState = !mState;
repaint();
}
// CustomItem abstract methods.
public int getMinContentWidth() { return 80; }
public int getMinContentHeight() { return 40; }
public int getPrefContentWidth(int width) {
return getMinContentWidth();
}
public int getPrefContentHeight(int height) {
return getMinContentHeight();
}
public void paint(Graphics g, int w, int h) {
g.drawRect(0, 0, w - 1, h - 1);
int stepx = 8, stepy = 16;
for (int y = 0; y < h; y += stepy) {
for (int x = 0; x < w; x += stepx) {
g.drawLine(x, y, x + stepx, y + stepy);
g.drawLine(x, y + stepy, x + stepx, y);
if (mState == true) {
int midx = x + stepx / 2;
int midy = y + stepy / 2;
g.fillTriangle(x, y, x + stepx, y, midx, midy);
g.fillTriangle(midx, midy, x, y + stepy,
x + stepx, y + stepy);
}
}
}
}
// CustomItem methods.
protected void keyPressed(int keyCode) { toggle(); }
protected void pointerPressed(int x, int y) { toggle(); }
}
|
The source
code bundle contains both the DiamondItem source code and
a MIDlet that demonstrates it, CustomItemExample. Here's a
screen shot of the running MIDlet:
DiamondItem screen shot
|
The Game API
The release of MIDP 2.0 is good news for game
developers.
Many of the release's enhancements can be found in the Game API, in
javax.microedition.lcdui.game.
The five classes in the Game API extend MIDP's
graphics capabilities in powerful ways. The basic concept is that the contents
of the screen can be composed of different layers. One layer might
contain the background. Another could show a spaceship, or a
hedgehog. Another layer could show fog, or clouds, or water, or anything else.
The basic class in the Game API is Layer, essentially just
a drawing surface with a location and size. Specialized subclasses
implement more specific functionality. TiledLayer is a
Layer whose contents are drawn from tiles contained in a source
image. Sprite is a Layer that animates
frames contained in a source image.
A LayerManager makes it easy to compose and render multiple layers.
GameCanvas is a subclass of Canvas. In addition to
Canvas's capabilities, it provides an offscreen buffer for fast,
flicker-free rendering and the ability to poll the states of the device's game
keys.
RGB Images
Another exciting advance for MIDP developers is the representation of images as
integer arrays, which allows MIDlets to manipulate image data directly.
Image data is represented as one int per pixel, with 8 bits each
for alpha (opacity), red, green, and blue values. The color components are
packed into the int as 0xAARRGGBB. For example, the
value 0xff00ff00 is fully opaque green, while
0x80ff0000 is half-transparent red.
MIDP 2.0's Graphics class supports RGB images with the following
method:
public void drawRGB(int[] rgbData, int offset, int scanlength,
int x, int y, int width, int height,
boolean processAlpha)
|
The rgbData array should have at least width * height
elements, starting at offset. The scanLength parameter
describes the number of pixels between consecutive rows in the integer array.
The x, y, width and height
parameters describe where the integer data should be rendered on the
Graphics' drawing surface. Finally, processAlpha is a
flag that indicates whether alpha compositing should be used. If it's
false, all pixels in the integer array are treated as opaque.
The following example, SnowCrash, is a Canvas that has
the dubious distinction of simulating video snow using an integer array. In the
source code bundle, the
RGBImageExample MIDlet demonstrates this Canvas.
import java.util.Random;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class SnowCrash
extends Canvas
implements Runnable {
private boolean mTrucking;
private int[] mRGB;
private Random mRandom;
public SnowCrash() {
mTrucking = true;
mRandom = new Random();
Thread t = new Thread(this);
t.start();
}
protected void randomize() {
if (mRGB == null) return;
int bitCounter = 0;
int r = 0;
for (int i = 0; i < mRGB.length; i++) {
// Get the next random int if necessary.
if (bitCounter == 0) {
r = mRandom.nextInt();
bitCounter = 32;
}
// Get the next bit.
int bit = r % 2;
r = (r >> 1);
bitCounter--;
// Set the color to black or white.
mRGB[i] = (bit == 0) ? 0xff000000 : 0xffffffff;
}
}
public void stop() { mTrucking = false; }
// Canvas abstract method
public void paint(Graphics g) {
int w = getWidth();
int h = getHeight();
int rw = 50;
int rh = 50;
int rx = (w - rw) / 2;
int ry = (h - rh) / 2;
if (mRGB == null) mRGB = new int[rw * rh];
// Clear the screen.
g.setColor(0xffffffff);
g.fillRect(0, 0, w, h);
// Draw the outline.
g.setColor(0xff000000);
g.drawRect(rx, ry, rw + 1, rh + 1);
// Draw the snow.
g.drawRGB(mRGB, 0, rw, rx + 1, ry + 1, rw, rh, false);
}
// Runnable method
public void run() {
// Attempt 12 fps.
int interval = 1000 / 12;
while (mTrucking) {
randomize();
repaint();
try { Thread.sleep(interval); }
catch (InterruptedException ie) {}
}
}
}
|
The following screen shot shows SnowCrash in action:
SnowCrash screen shot
|
Permissions and Code Signing
MIDlets that use the Generic Connection Framework may cost users money (in the
case of network connections) or involve a security risk (in the case of serial
port access).
In light of the sensitivty of the connection framework, the MIDP 2.0
specification recognizes the concepts of trusted and untrusted code and
permissions. Untrusted code cannot make connections at will; it
must receive permission from the user. Code can be designated as trusted if the
developer digitally signs it and the user's device can verify the signature.
The exact mechanics of asking and granting permission depend on the security
policies of the device and those defined by the user.
As an example, consider a game that connects to a server to maintain a
community list of high scores. If the game is not signed, or is
signed by an entity the device doesn't recognize,
the code is untrusted. When the game attempts to
connect to the high-score server, the MIDP 2.0 implementation denies the action
(by way of a runtime
SecurityException) or, more likely, prompts the user to
allow or deny the network connection.
If the game is signed and the device verifies the signature, the code
can be designated as trusted and allowed to make its network connection.
Special
entries in the manifest file allow MIDlet suites to indicate which permissions
they require in order to run smoothly. The MIDP 2.0 specification defines
permissions for various types of network connections. It is an extensible
architecture, and optional packages that deal with sensitive APIs will likely
define additional permission types.
For full details of permissions and code signing, see the documents entitled
Security for MIDP Applications and Trusted MIDlet Suites Using
X.509 PKI in the MIDP 2.0 specification.
Other New Features
This article describes some of the flashier new features in
MIDP 2.0; there are many more, including:
- Standardized connection strings for serial port access.
- Standardized connection strings for datagram, socket, and server socket
connections. The specification doesn't require support for these types
of connections but it recommends their implementation and provides supporting
APIs.
- A push registry that allows MIDlets to be launched in response to
incoming network connections.
- The Over-the-Air (OTA) recommended practice, an addendum to the MIDP 1.0
specification, is now incorporated in the MIDP 2.0 specification.
- The
MIDlet class has a new platformRequest()
method that asks the underlying platform to display a URL.
- Record stores may be shared between MIDlets.
Summary
MIDP 1.0 established a standard Java environment for small devices with wireless
network connectivity. MIDP 2.0 expands considerably on the original
specification with far-reaching support for advanced user interfaces,
multimedia, secure HTTP networking, and many other useful features.
About the Author: Jonathan Knudsen
[e-mail]
[home page]
is the author of several books,
including
Wireless Java (second edition),
The Unofficial Guide to LEGO MINDSTORMS Robots,
Learning Java (second edition), and
Java 2D Graphics.
Jonathan has written
extensively about Java and Lego robots,
including articles for JavaWorld, EXE, NZZ Folio,
and the O'Reilly Network.
Jonathan
holds a degree in mechanical engineering from Princeton University.
Back To Top
|
|