★ wanayoo — archive 1999 http://java.oreilly.com/bite-size/java_0300.htmlNouvelle recherche | Portail wanayoo
Bite-Size Java
O'Reilly HomeO'Reilly Network
ConferencesSoftwareInternational

Arrow Search
Arrow Product List
Arrow Press Room
Resource
Centers

Arrow
Perl
Java
Web & Internet
Open Source
Linux
Unix
Macintosh
Windows
Oracle
Security
Sys/Network Admin
C/C++ Programming
Design & Graphics
Visual Basic
Java 2D Graphics
Special
Interest

Arrow
Ask Tim
Frankly Speaking
Bite-Size Java
Ron's VB Forum
Conferences
Beta Chapters
PalmPilot
Books Online
Specials
Write for Us
Work with Us
O'Reilly
 

Jonathan Knudsen There's a Socket in my Pocket

by Jonathan Knudsen


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.

Small Java for Small Devices

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.


Want to learn more about Java? Check out The O'Reilly Conference on Java, March 27-30, in Santa Clara, CA.

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.

Building KVM Applications

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.

Using the Emulator

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.

Sockets on the Palm

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.)

Sockets in POSE

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.

Fire It Up

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.

Going Forward

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.

O'Reilly Home | O'Reilly Bookstores | How to Order | O'Reilly Contacts
International | About O'Reilly | Affiliated Companies

© 2000, O'Reilly & Associates, Inc.
webmaster@oreilly.com