Sync up Palm OS with J2ME
Develop Palm HotSync conduits that interact with MIDP apps
Have you used any standalone applications for your mobile device lately? Probably not; most applications would be useless without some communication to the outside world. For example, doctors and nurses now use their PDAs to obtain the latest medical information stored in databases residing on the Internet. Also, a variety of handheld devices offer real-time securities-trading software. In short, handheld devices provide a portable way to view information that changes day-to-day, hour-to-hour, or minute-to-minute.
Java 2 Platform, Micro Edition (J2ME) features all the tools developers need to create platform-independent applications for mobile devices. Its MIDP (Mobile Information Device Profile) technology lets you quickly and easily bring complex, form-based applications to market for a wide range of handhelds.
We typically categorize handheld devices by their accompanying operating systems. The major players include Pocket PC and Windows CE, from Microsoft, and Palm OS, from Palm. Palm OS generally runs on a significantly cheaper device, which could explain Palm’s market dominance and success as a highly desirable platform for application development. The low cost of Palm OS-based devices make them an excellent choice for application distribution, where a buyer purchases a device solely for application use. A doctor, for example, might use a PDA not to manage his schedule, but to access the various medical databases available for handhelds.
The HotSync technology for Palm OS is an application installed with the desktop software distributed with every Palm OS-based handheld. Using a serial or USB (universal serial bus) cable, HotSync transfers applications and data through conduits that plug in to the HotSync Manager. HotSync has achieved an overwhelming degree of success. Conduits can be found in applications ranging from Intellisync for Yahoo!—which synchronizes personal information to your Yahoo Profile—to Delta Airlines’ conduit, which allows users to obtain flight information over the Internet.
Many mobile applications rely on some form of communication with a central information system, possibly residing on the Internet. For many handheld applications, wireless is not an option, but HotSync might be. Palm’s wireless Internet provider, Palm.Net, is still relatively expensive at 0 per month for unlimited access, and many users might find themselves without coverage if they stray from metropolitan areas. If their applications are Web-clipped or stream-based and depend on a connection, users might find themselves out of luck. HotSync allows users to transfer data stored on their PDAs at their convenience.
Having said that, however, I must also point out that HotSync does not fall into the MIDP specification and hence is not supported by Sun Microsystems. The question now arises whether implementing a MIDP application that relies on a HotSync conduit is sound. Have you defeated the point of using Java to create a platform-dependent application, when you could have used the native C libraries? Hardly: By developing a HotSync-based MIDP application, you save yourself a considerable amount of time and money, and leave open the possibility to decouple yourself from Palm OS at any time. For example, with MIDP, you can easily create GUI (graphical user interface) elements such as drop-down boxes. MIDP developers need not concern themselves with the diligent search for memory leaks, which can crop up in C development. In addition, the MIDP specification supports the standard HTTP protocol, which can replace the HotSync logic when a situation calls for it. You should take advantage of the HotSync technology, as you can easily develop and distribute a wireless solution later.
Though MIDP lacks HotSync support, the spec does support persistent storage for Palm OS and maps handily to the persistent storage Palm currently uses. If you’re developing any commercial-grade application, you usually need persistent storage—especially if your application communicates with another data source outside your handheld device. Once you get information from your data source, you need somewhere to put it. The MIDP specification includes persistent storage, which resembles the implementation used in Palm OS.
This article addresses how to combine your desire to use HotSync with your need for persistent storage to transfer your data source’s information. I discuss the problems that arise when using a HotSync conduit to transfer information stored by a MIDP application on a Palm OS-based PDA and show you how to develop a HotSync conduit that successfully interacts with a MIDP application.
The first step in developing a Java-based HotSync conduit is acquiring the following tools:
- Obviously, you’ll need Sun’s Java 2 SDK; version 1.3 is preferred for conduit development.
- Sun’s J2ME Wireless Toolkit (JWTK) contains several handy tools and the necessary libraries to develop MIDP applications. Though not required for conduit development, the JWTK is needed for developing an application with which to test said conduit. Borland’s JBuilder MobileSet offers an alternative to the JWTK.
- Next, install Palm’s latest version of the Conduit Development Kit (CDK).
- To run the sample MIDP application, you need the Palm OS Emulator.
- Finally, install a null modem cable as specified in the CDK documentation.
We start by creating a simple MIDP application using the JWTK. This application tests the conduit, which we will create later, and highlights the inconsistencies when trying to use the CDK sample conduits with a MIDP application. We begin with a simple HelloMidlet
, which displays a simple text field:
public HelloMidlet()
{
// Retrieve the display from the static display object
midletDisplay = Display.getDisplay(this);
// Initialize the doneCommand
doneCommand = new Command("DONE", Command.SCREEN, 1);
}
public void startApp()
{
Form f = new Form("Hello");
TextField hello = new TextField("Hello:",null, 20, TextField.ANY);
f.append(hello);
midletDisplay.setCurrent(f);
}
Note: For a comprehensive guide on creating MIDP applications, see Michael Cymerman’s JavaWorld series “Device Programming with MIDP.”
As alluded to previously, this application needs persistent storage to be of any use.
How does Palm OS implement persistent storage?
The Palm OS features two database types: resource and record databases. We will deal exclusively with the latter. Each database consists of a header block, followed by an arbitrary data block. The header block contains:
- Name
- Creator ID
- Type
- Number of records
- Last synchronization date
A creator ID is a four-character piece of code that can be registered with Palm to ensure uniqueness. Each record in the data block contains:
- Record ID
- Record category index
- Record attributes
- Record data
How does MIDP treat persistent storage?
A MIDP application maintains an RMS (Record Management System) record store for persistence storage. An RMS record store has only a one-dimensional structure with sequentially ordered data fields. In short, it’s a list of byte arrays. A standard Palm OS record database also stores records this way.
You use the following methods to load and save the text field’s contents of our HelloMidlet
sample in an RMS record store:
public void loadText()
{
try
{
// Load the text field
RecordStore rs = RecordStore.openRecordStore("Hello" ,true);
if (rs.getNumRecords() > 0)
hello.setString(new String(rs.getRecord(1)));
rs.closeRecordStore();
}
catch(RecordStoreException rse) { System.out.println(rse); }
}
public void saveText()
{
try
{
// Save the text field
RecordStore rs =
RecordStore.openRecordStore("Hello" ,true);
byte[] bytes =
hello.getString().getBytes();
if (rs.getNumRecords() < 1) rs.addRecord(bytes,0,bytes.length);
else
rs.setRecord(1,bytes,0,bytes.length);
rs.closeRecordStore();
}
catch(RecordStoreException rse) { System.out.println(rse); }
}
The MIDP RMS specification maps almost exactly to Palm’s persistent storage implementation, with just a few subtle differences: The call to openRecordStore()
does more than simply open an existing record store. Upon attempting to open a nonexistent record store, the method call dynamically creates one. However, when a non-MIDP application attempts to access a database created by a MIDP application, it faces some difficulty. Specifically, the non-MIDP application has trouble dealing with this new database’s header and name. The openRecordStore()
method contains only one string argument, which is the record store’s name, but additional items are needed for creating the header. For the above example, MIDP generates the following database header:
- Database name:
Hello-VM00
- Creator ID:
VM00
- Application information block:
byte[] { 0, (byte)'H', 0, (byte)'e', 0, (byte)'l', 0, (byte)'l', 0, (byte)'o' }
- Type:
RMSd
If a MIDP application using creator ID VM00
previously exists on the device, then VM01
would be used. This presents an interesting dilemma. If you desire access to the database using any source besides MIDP, it might prove difficult to determine the creator ID or database name. The solution: Use a conduit to create the database before the MIDP application ever accesses it.
What is a conduit?
According to Palm, conduits are:
Applications that plug in to HotSync technology, transferring information to and from a Palm Computing platform device, usually with some data manipulation in the process.
When a user drops a connected organizer into its cradle and presses the HotSync button, the HotSync Manager runs the conduits, which reside on the user’s computer. Conduits also transfer, import, and export data, and install Palm OS applications. The Java conduits are geared towards two areas where development proves easier in Java than other languages: Internet/intranet applications and corporate database access through a JDBC (Java Database Connectivity) interface. See the figure below for an example of a conduit.
How does a Java-based conduit treat persistent storage?
Now that we know what conduits are and would like to use one with our application, we need to understand how they interact with MIDP. Upon examining the CDK’s sample Java conduits, we find that though they read data, no Java conduits actually write data to the Palm. However, the conduit API contains the necessary methods to write to a standard Palm OS database. The following code segment demonstrates a conduit that writes data while considering the aspects of the MIDP specification discussed above. First, we initialize the necessary variables holding information relevant to the MIDP spec, then attempt to create/open the database:
/** Open and run the conduit */
public void open(SyncProperties props)
{
// Tell the log we are starting
Log.startSync();
Log.out("Hello conduit: initialize conduit");
int db = 0;
String dbName = "Hello-VM01";
String source = "";
try {
// Read the source string from the file
FileReader fr =
new FileReader("c:j2mewtkappsHelloMidletin.txt");
source = (new BufferedReader(fr)).readLine();
// Try and create DB
try
{
Log.out("HelloCond: creating " + dbName);
// Create integer version of creator id
int creatorId = 0;
creatorId |="V";creatorId <<=8;
creatorId |="M"; creatorId <<=8;
creatorId |="0"; creatorId <<=8; creatorId |="1";
// Create integer version of type
int dbType = 0;
dbType |="R";dbType <<=8;
dbType |="M"; dbType <<=8; dbType |="S";
dbType <<=8; dbType |="d";
// Create PDB
db = SyncManager.createDB(creatorId, 0, 0, dbName, dbType);
// Write app info block
byte[] appInfoBytes = new byte[] { 0, (byte)'H',
0, (byte)'e', 0, (byte)'l',
0, (byte)'l', 0, (byte)'o' };
SyncManager.writeDBAppInfoBlock (db, dbName, appInfoBytes);
}
catch (Exception e) { /* do nothing here */ }
Before opening the database, the conduit tries to create a new one, and if unsuccessful, it discards the resulting exception. If the database already exists, the call to SyncManager.createDB()
throws an exception. We discard this exception in the catch
block, since the database exists for any conduit execution (other than the first). If properly installed, the conduit runs before the first MIDP application executes. If designed this way, the conduit creates the database, eliminating any ambiguity as to the database’s name and creator ID.
The following code performs the actual write to the previously opened database:
// Open Palm DB
Log.out("WebspectCond: opening " + dbName);
db = SyncManager.openDB(dbName, 0,
SyncManager.OPEN_READ |
SyncManager.OPEN_WRITE |
SyncManager.OPEN_EXCLUSIVE);
// Write the appropriate record
HelloRecord hr = new HelloRecord();
hr.setMsg(source);
hr.setIsNew(true);
hr.setIsModified(true);
hr.setIndex(SyncManager.getDBRecordCount(db));
Record r = (Record) hr;
r.setId(1);
SyncManager.writeRec(db, r);
SyncManager.closeDB(db);
} catch (Throwable t) {
// If there was an error, dump the stack trace
// and tell the log the conduit failed
t.printStackTrace();
Log.err("WebspectCond: aborting sync");
Log.abortSync();
}
}
Note that a pitfall of performing database writes is the Record.setId()
call. If an invalid record ID is assigned, the entire RMS record store becomes unusable. The valid range for record IDs is one through the current number of records plus one. Also note that this solution limits you to creator IDs VM00
through VM99
.
Get in sync
In this article, I demonstrated one strategy for effectively implementing a conduit while conforming to the MIDP RMS specification. This approach should tempt many developers due to HotSync’s wide acceptance and the variety of conduit samples available. The solution lets you apply your existing Java knowledge to yet another area.
The beauty of an effective object-oriented design is that, should you wish to decouple the application from the Palm OS, you can replace HotSync with HTTP. To do that, simply add one button to the MIDP application so the user can transparently move from a HotSync-based solution to an HTTP solution. Taking advantage of HotSync initially allows developers to bring Palm-based applications to market much faster. HotSync is a robust, stable technology that, when developing for Palm OS, every MIDP developer should leverage.