|
Sun has its sticky Java fingers in a lot of different pies. In this
article I'll explore one of these pies, the small device market. This includes
platforms like PalmPilot and Visor as well as mobile telephones. It's a
huge, expanding market. As more small devices get wired (figuratively speaking)
to the Internet, applications can take advantage of downloadable code,
which is something Java does well.
Small device programming gets really interesting when a network is involved.
In Java, network programming is oriented around the java.net.Socket
class. This month's column presents a hands-on introduction to using
Sockets on a PalmOS device.
Sun has a special version of the Java 2 platform for small devices. It's
called Java 2, Micro Edition (J2ME). Currently it's based around a tiny
Java virtual machine called the KVM and a tiny subset of the core Java
APIs. (The KVM gets its name because its size is measured in kilobytes
rather than megabytes.)
J2ME uses PalmOS devices as its reference platform, although the KVM
has been ported to dozens of platforms. In this column, we'll work with
the J2ME reference implementation for Palm.
You can download the KVM by following a link off
Sun's
official page. The KVM is currently in the early access phase, which
means it's not very stable and the APIs are likely to change. The code
in this column was compiled with Developer Release 4.1, also called Early
Access 2 (ea2). The KVM download includes instructions for placing the
KVM on your PalmOS device. It also includes sample applications and some
documentation.
For other useful information and code for the KVM, you should also check out
Bill
Day's application archive.
The core of the KVM development process is the same as for any Java application:
use the javac compiler to convert .java source files into
.class
files. However, there are two important differences.
First, KVM applications should be compiled with reference to the KVM
APIs, not the regular JDK or JRE APIs. The key to this is javac's
-bootclasspath option. This options lets you specify a classpath to
be used for the core Java packages. For example, the following command line
compiles a KVM source file:
javac -bootclasspath ..\api\classes -classpath classes -d classes src\PocketSocket.java
The -bootclasspath option points to the KVM classes. I've also
included the -classpath option, in case this application spans
multiple classes. The classes directory will be searched for additional
application classes. The -d option specifies that compiled classes
should go into the classes directory. Finally, the source file is
PocketSocket.java, in the src directory. When you compile
the examples from later in this column, you'll use a similar command line,
modified for your particular directory structure.
The second unique aspect of building KVM applications is that they need
to be packaged for PalmOS. Fortunately, Sun provides a tool for this with
the KVM download. It's a Java class called palm.database.MakePalmApp.
The example applications that come with the KVM include shell and batch
files that demonstrate how to use this tool. In essence, it takes the one
or more .class files of your application and packages them in a
.prc file that can be downloaded to your PalmOS device.
Once you've got a .prc file, you can use an install tool to get
the application on your PalmOS device.
If you don't actually have a PalmOS device, you can simulate one instead.
Palm provides an outstanding emulator, the PalmOS
Emulater (POSE). POSE is an application that acts just like a Palm
III, V, or VII. It's very handy for developing new applications. Even if
you own a PalmOS device, you might want to use the emulator to shorten
your development cycle.
You can download POSE for free. You'll also need a set of PalmOS ROM
images so the emulator can boot. There are instructions for downloading
ROM images on the POSE download page. You'll need to jump through some
hoops and fill out some forms. If you already own a PalmOS device, it may
be quicker to simply upload the ROMs from the device. POSE can do this;
check the documentation.
Once you've got the emulator up and running, you can download the KVM
and other .prc files to it, just as with a real PalmOS device.
A Socket in a Palm KVM application refers to a network connection
made over the Palm's serial port, either using a modem or a direct connection
to a PC. PalmOS includes a networking library called NetLib. The Socket
class in the KVM is layered on top of NetLib.
The modem is the most likely means of communication; PalmOS has facilities
for setting up a Point-to-Point Protocol (PPP) connection with an Internet
Service Provider using a Palm modem. (With the direct connection to the
PC, the communication is still over PPP.
Click
here for instructions on setting up Windows NT as a PPP server.)
It's actually a little easier to connect POSE to the network. While POSE
is running, right-click for a menu. Choose Properties... In the
Communications
box, make sure Redirect NetLib calls to host TCP/IP is checked.
When your application tries to make a network connection, the emulator
will actually use whatever network connection is available on your PC.
This can make testing a lot easier than a long cycle of downloading your
application to the Palm, dialing up your ISP, and running the application.
Let's look at a simple example, an application that connects to a web server.
We won't actually download any data; we'll just connect to the server and
declare victory.
Most of this example has to do with creating a user interface for the
application. We use Palm-specific classes for this, in the com.sun.kjava
package. This stuff is fairly buggy, and will probably change before
the final release of the KVM, so don't take it too seriously at this point.
import java.io.IOException;
import java.net.Socket;
import com.sun.kjava.*;
public class PocketSocket
extends Spotlet {
protected static final String kDefaultHost = "www.oreilly.com";
protected static Graphics sGraphics;
public static void main(String[] args) {
// Clear off the KVM splash screen.
sGraphics = Graphics.getGraphics();
sGraphics.clearScreen();
// Create a new application.
Spotlet s = new PocketSocket();
// Register to receive events.
s.register(NO_EVENT_OPTIONS);
}
private TextField mHostField;
private Button mConnectButton;
private String mStatus;
public PocketSocket() {
// Create the Host field and give it focus.
mHostField = new TextField("Host", 0, 0, 104, 12);
mHostField.setText(kDefaultHost);
mHostField.setFocus();
// Create the connect button.
mConnectButton = new Button("Connect", 120, 2);
// Display a welcome message.
setStatus("Welcome to PocketSocket");
}
public void paint() {
// Paint UI controls.
mHostField.paint();
mConnectButton.paint();
// Draw status message.
sGraphics.drawRectangle(0, 147, 159, 12, Graphics.PLAIN, 0);
sGraphics.drawString(mStatus, 0, 147, Graphics.INVERT);
}
public void keyDown(int key) {
if (mHostField.hasFocus()) mHostField.handleKeyDown(key);
}
public void penDown(int x, int y) {
if (mConnectButton.pressed(x, y)) connect();
}
protected void setStatus(String message) {
mStatus = message;
paint();
}
protected void connect() {
try {
setStatus("Connecting...");
String host = mHostField.getText();
Socket s = new Socket(host, 80);
setStatus("Connected to " + host);
s.close();
}
catch (IOException ioe) {
setStatus("Connection failed: " + ioe.toString());
}
}
}
As I said, a lot of this example is concerned with user interface. The
actual network stuff is in the connect() method, and looks just
like Socket programming in other Java applications. Interestingly,
if the connection fails, the exception handler is never invoked. Instead,
the Palm screen displays an error message and you get booted out of the
PocketSocket application. Presumably, this is a bug, something that
will be cleared up in later KVM releases.
PocketSocket extends the Spotlet class, which represents
an application in PalmOS. Spotlet tells us when events occur,
like the user writing letters or tapping elsewhere on the screen. You'll
see how this works when we look at the keyDown() and penDown()
classes.
The main() method clears the screen, which still shows the
KVM splash screen as our application begins. Then main() creates
a new instance of PocketSocket and registers it to receives events.
The NO_EVENT_OPTIONS parameter means we're not interested in receiving
events when the system keys are pressed. (System keys are the buttons on
the bottom of the Palm devices, with icons for date book, telephone list,
to-do list, and memo pad.)
PocketSocket's constructor sets up the user interface components
and displays a welcome message. The paint() method calls the
paint() methods of the interface components and draws the status
message in a bar at the bottom of the screen. Spotlets process events
when their keyDown(), penDown(), penMove(),
and penUp() methods are called. In this application, we simply
pass key and pen events (in keyDown() and penDown())
on to the Host text field or the Connect button. In
penDown(), we ask the Button if the event pertains to it
by calling pressed(). If it does, the Button will show
itself being pressed and the pressed() method returns true.
In this case, we call our connect() method.
The setStatus() method simply stores away a status string and
repaints the application to show the new message.
The connect() method contains all the network code. All we
do is try to create a Socket, using port 80 to connect to a web
server.
We've covered some important ground here. Fundamentally, it's nothing new:
all we did was create a Java application that connects to a computer on
the network. But networked applications on small devices--now that's something
exciting, particularly when you start thinking about wireless devices.
Mobile telephones already have network applications developed in
platform-specific ways. Whether J2ME will catch on as a development and
deployment environment is anyone's guess.
Download the source code.
Jonathan
Knudsen is an author and developer at
O'Reilly & Associates. He is the
author of The Unofficial
Guide to LEGO® MINDSTORMS Robots,
Java 2D Graphics,
and Java
Cryptography.
|