 | Level: Intermediate Michael Abernethy (mabernet@us.ibm.com), Java consultant, IBM
01 Jan 2003 If you want to spiff up your mobile device performance, let Michael teach you not only how to write a J2ME application that communicates with DB2, but how to optimize its development time. You'll also look over other design models that should be employed for better mobile device optimization. In addition, you'll be introduced to the new technologies in MIDP 2.0 -- specifically SMS messaging and how it relates to the future of mobile device applications.
The cell phone business is growing at a breakneck pace, and keeping up with the latest technologies is a full-time occupation. In this article, I'll offer an update on what's currently available to the
mobile device developer. I'll also include a rundown on the emerging technologies in the field, along with tips for integrating them into mobile applications.
Before jumping into the example application -- BagTracMobile -- it's important to understand the basic setup of the
J2ME architecture and the J2ME Toolkit, and how they relate to the mobile devices currently on the market. In the Resources section at the end of this article, you will find several links to sites that can get you started on learning and understanding J2ME. This article assumes you have an intermediate knowledge of J2ME and the concepts of MIDlets, of .jad files, and how to
use the J2ME Toolkit to test and debug applications. (If none of that made any sense, then you might be a
candidate for some background learning before jumping into this article.) The listed resource articles are perfect
for beginners wanting to learn how to develop MIDlets and the basic concepts of J2ME application development. Here, however, I will dig deeper into
J2ME and examine design patterns and development issues unique to the smaller devices.
I'm going to set up BagTracMobile, a simple baggage tracking application. Like most typical wireless applications, it's going to be a client application that talks to the server via a servlet. Just because
we're on a mobile device doesn't mean we have to change anything as far as that goes. The mobile devices
are almost like a time warp of programming today -- you get all the modern amenities of easy network
connections, object-oriented programming, and power IDEs, but you have to use them to program machines that
have only the same memory and clock speed of computers of the late 1980s. Just be thankful it's not the other
way around -- using punch cards to program today's 3 GHz monsters.
Getting started
Most J2ME applications will extend the javax.microedition.midlet.MIDlet class, and with it,
the MIDlet's three abstract functions: destroyApp(),pauseApp(), and startApp(). If this looks familiar, it
probably is; it's nearly the same setup as an applet, but with different function names. So, the simple
way to think of a MIDlet is as an applet running on a mobile device.
However, before the startApp() function is called, there are some important things to do in the
constructor of the MIDlet. First, grab
the instance of the Display object, then instantiate any Command objects you will be using, and load any needed images into the application. The code goes as follows:
public BagTracMobile()
{
display = Display.getDisplay(this);
exit = new Command("Exit", Command.EXIT, 1);
query = new Command("Trac", Command.SCREEN, 1);
back = new Command("Back", Command.BACK, 1);
enter = new Command("Enter", Command.SCREEN, 1);
try
{
saveImage = Image.createImage("/icon.png");
}
catch (IOException e) { e.printStackTrace(); }
} |
Now that we have an instance of the Display object used in the MIDlet and the Commands we are going to use, we
can start to develop the screens we'll be using in the application.
Screen development ScreenFlow model
All the screens in this application were developed following the ScreenFlow model. The
basic premise of this model is that every screen knows how to handle itself, how to display its data,
and how to perform its functions. It almost seems like this model is begging to make each screen its own class,
and in a normal application on a normal workstation, I would definitely agree. However, because we are on
a cell phone with limited resources, we have to keep a couple of things in mind:
- Every class in the application brings with it some size overhead. You have to create constructors, variables, and functions for every class you create.
- Every class has to be loaded into memory when it is used.
These two things should cause sirens to go off in your head as you plan your mobile device
applications. Space and memory
are the cheesecake and ice cream on top of the mobile device world; you should cherish every bite (byte?) of
them and
keep as much of them nearby for as quick consumption as possible. So, what does this mean for screens? In a nutshell, make each screen its own function. This is the happy medium between making each screen its own class
and creating every screen with reams of code in the constructor. In addition, the relative simplicity of each screen on
mobile devices lends
itself well to this model. Each screen will contain only a few components, which makes the coding for each
screen very manageable. Here's another quick tip along the same lines: When you're using data objects, there's no
need to use get/set methods; just make every variable a public one, and you can save lots of space.
Let's look at the opening screen as an example:
Figure 1: Opening screen

Like all cell phone screens, it contains few components and is easy to code:
// Always create a Form - this will be the base to which you will add
all the components
formStart = new Form("BagTrac");
// create the visual components we'll be using and add them
// to the form
choiceGroup = new ChoiceGroup("Search Type", List.EXCLUSIVE);
choiceGroup.append("New", null);
choiceGroup.append("Saved", null);
formStart.append(choiceGroup);
// now we add "buttons" to the screen for action. Of course,
// they're not really buttons but rather choices presented to the
// user on the phone display.
// These commands have been statically initialized in the constructor for
// faster execution and reuse
formStart.addCommand(command_exit);
formStart.addCommand(command_enter);
formStart.setCommandListener(this);
// finally, display the screen
display.setCurrent(formStart); |
Event handling ScreenFlow model, continued
In MIDlet development, all "button" events are passed along to the public void commandAction() method,
which takes two parameters: the Command object that threw the action, and the Displayable object from where
the Command object was thrown (the Displayable object is simply the screen). From these two pieces
of information, we can handle any event that the application throws at us; we know the screen, and we know
the "button" that was pressed, and now it's just a matter of some if/else chains to handle the action.
Does this approach also sound familiar? Again, it probably should, as it shares a lot of similarities with the
event model in Java 1.0 language. You remember that public boolean action() and public boolean handleEvent() with
those huge if/else chains? Don't worry, things won't get that ugly in these applications; there aren't
enough screens or "buttons" for that.
The ScreenFlow model also allows us to optimize our event handling. We can use the knowledge that nearly
all mobile device applications will fit the model of a tree navigation to save a lot of coding.
Figure 2. Screen flow of BagTracMobile

Figure 3. Screen flow of a fictional application

Examine the tree format and you will see that whenever we press "Back", we return to the screen we were
on previously. By simply keeping track of the screens as we go, we can eliminate at least half of the checking.
To this end we can use a java.util.Stack and simply push() the screens when we go forward, and pop()
the screens as we go backwards. Now, whenever the "Back" "button" is pressed, instead of checking which
screen we're on and to which we need to return, we can simply just go there, as you can see here:
if (command == command_back)
{
displayable = null;
display.setCurrent((Form)screenStack.pop());
} |
That takes care of backward traversal, but we still have to concern ourselves with forward traversal. Because we know which
screen we're currently on, and which button was pressed, it's just a matter of writing that if/else chain.
Keep in mind that when you move forward a screen, you need to add the current screen to the stack.
else if (command == command_enter)
{
screenStack.push(displayable);
if (choiceGroup.getString
(choiceGroup.getSelectedIndex()).equals("New"))
screenNew();
else if (choiceGroup.getString
(choiceGroup.getSelectedIndex()).equals("Saved"))
screenSaved();
} |
For more complex screen flows, it may even be optimal to set up a Tree data structure,
where each screen is a node, and each "button" is a path of that node. The goal is to keep
the if/else chains to a minimum, both for code maintainability and also code size. While this
application only has four screens, a larger app could lead to lengthy if/else code, which is
always a no-no.
Network communications HttpMobile
The network communications portion of BagTracMobile is even easier than the GUI portion. As we are querying the database for baggage information, we need to talk to
the servlet, which will talk to the database. Setting up the network communication is surprisingly simple,
though. The J2ME structure masks all the inner workings of the communication from the coder through the
factory Connector class. By passing an address to the Connector class and then casting its returned
Connection class, you can easily get your desired communication.
public static String doGet(String address, String arguments)
{
HttpConnection http = (HttpConnection)Connector.open(address + arguments);
http.setRequestMethod(HttpConnection.GET);
InputStream in = http.openInputStream();
int input = 0;
StringBuffer response = new StringBuffer();
while ((input = in.read()) != -1)
{
response.append((char) input);
}
in.close();
http.close();
return response.toString();
} |
In fact, the network communication is generic enough that we can move it out of BagTracMobile
and create a new HttpMobile class that handles HTTP communication exclusively. This factory class
offers a doGet() method and a doPost() method, while removing the networking functionality from the
MIDlet and putting it into its own reusable component.
Communicating with DB2
Normally, when communicating with a database, the size of the data object being sent and returned
is not at the top of the list of concerns. As you can imagine, that is not the case with mobile device applications. The size of the data being sent and returned in this case is at the top of the list
of concerns. When
designing a mobile app that will be communicating with DB2,
the "Lawyer Model" must be employed.
The Lawyer Model
The Lawyer Model states that every request to the database
gets as short a response as possible while still answering the request. Consider this in terms of all those courtroom/police
dramas on TV -- a lawyer, when asked any question, will only answer as succinctly as possible and give out no other
information. This should be the design goal of any database code when working with mobile device apps: no
extraneous information; return only what the application needs to have.
In the BagTracMobile example, the mobile portion of the application passes the bag number to BagTracMobileServer.
BagTracMobileServer queries DB2 and gets a ResultSet containing every scan for that bag number. However,
because the mobile app is only requesting the most recent scan, BagTracMobileServer employs the Lawyer Model
and disregards all the old scans, returning only the information on the most recent scan.
In addition to the data size, consider many other constraints when coding a mobile device
app that communicates with DB2 and attempts to display its results:
- Screen size: It is difficult to show something even as simple as a table, so if you decide you must have that table anyway,
expect, at most, 2-3 columns and 4-5 rows visible at one time.
- Slow transmission speed: Granted, the new cell phone networks are advertised to be faster,
144 kbps on the CDMA and 112 kbps on the GSM/GPRS networks, but that's optimal download. On my phone now, I'd
estimate it to be around 9 kbps. Sending data is even slower.
- Slow processing speed: If you do choose to return a large result set, the slow processing
speed on the device will cause a delay because the device will take a while to process it and display it.
Cell phones typically have
20-40 MHz processors, typical of the desktops from the prehistoric era of computing in the early 1990s.
- Cost: Many of the cell phone companies charge by the Kb sent over their network.
On this last point, it's easy for me to start ranting. The wireless companies really need to reconsider this pricing plan. It's
modeled after the Asian and European systems, and fails miserably to take into account our very real culture differences. The wireless companies complain that few people are attracted to the new fast
wireless networks they're setting up, but with these pricing plans, it's not surprising. American consumers, as a
whole, do not pay for things as they go. American consumerss like to pay a chunk of money and get a fixed product.
They don't like surprises with each bill. They'd rather pay a lump sum and not have to think about it again.
Think about what happened to AOL's pay-by-the-hour plan -- it's gone. Would you like a cable
plan that makes you pay by the hour as you watch television? By the same token, I believe it's this pricing plan that is holding back much of
wireless technology and hurting the consumers.
So, with all these caveats in mind, remember that the DB2 and server side code must be
coded in such a way as to optimize its
communication with the mobile devices. As the Lawyer Model dictates, pass around as little information
as needed from mobile device to server, let the processing speed of the server handle all the data
manipulation and computations (the server side processor will be about 100x faster), and do not expect,
in most cases, to show a table of results to the user.
Record storing
Like any application on a computer, a mobile device application might need to physically store information
in a file for later use. In an effort to make this application easier to use, we should store the bag
numbers that people have recently entered, so that they don't have to enter them again and again.
For this, we use the classes in the javax.microedition.rms package, which allow us to use a flat
file to store information on the phone.
The J2ME documentation states that it is up to the mobile device itself to decide where and how this
information gets stored. Luckily all that decision making is hidden from the developer. However,
the maximum size of the flat file is also up to the mobile device, and this we do need to worry about.
In the phone documentation that I've come across, the smallest figure I've seen is 2Kb max size, and
of course, in this line of application development, you must always code for the lowest common denominator.
So, assume that 2Kb is the maximum size of your file. In this application, I've deleted from the file every record
that's more than 60 days old in order to ensure that frequent travelers will be able to store as many
bags as possible.
The RecordStore class acts as a primitive database flat file manager, so that when it is opened, it parses the
file into records. Using this knowledge, we know we might have to parse the file for the information
we want each time we open it.
RecordStore recordStore = RecordStore.openRecordStore(RECORD_FILENAME, true);
// delete all records older than 60 days
int size = recordStore.getNumRecords();
for (int i=0; i less than size; i++)
{
String record = new String(recordStore.getRecord(i+1));
long time = Long.parseLong(record.substring
(0, record.indexOf(BagTracConstants.DELIM)));
long deleteOffset = System.currentTimeMillis() -
(1000 * 60 * 60 * 24 * BagTracConstants.DELETE_DAYS);
if (time less than deleteOffset)
recordStore.deleteRecord(i);
}
// return most recent searches first
RecordEnumeration iter = recordStore.enumerateRecords
(null, new BagTracComparator(), true);
while (iter.hasNextElement())
{
String record = new String(iter.nextRecord());
String number = record.substring(record.indexOf
(BagTracConstants.DELIM)+1);
savedNumbers.addElement(number);
}
recordStore.closeRecordStore(); |
As you can see in the class RecordEnumeration, there is a close resemblance to the Enumeration class in J2SE.
We create a BagTracComparator class, which is an implementer of RecordComparator, and must implement one
method -- the public int compare(byte[ ], byte[ ])method. Using this one line, we effectively sort our
records in the file, and then loop through them and add them to the class variable that stores them.
Saving information in the RecordStore is just as easy. By simply opening up the file and writing to it,
we've created another record in the file.
RecordStore recordStore = RecordStore.openRecordStore(RECORD_FILENAME, true);
long millis = System.currentTimeMillis();
String record = "" + millis + BagTracConstants.DELIM + number;
recordStore.addRecord(record.getBytes(), 0, record.length());
recordStore.closeRecordStore(); |
Bonuses
At this point the application is text-only, but we can add a few images to
spruce it up a little. Because we've already loaded our image in the constructor for BagTracMobile, we
can use the image anywhere necessary. In fact, looking at the API for the GUI components in MIDP,
we can see that nearly every one of them takes an Image object as a parameter. In our app, we'll use a little suitcase icon next to the saved numbers to make our app look more professional.
Note: At this stage, only .png files can be used as image files. Also keep in mind that the .jad file
and .jar files for the phone will have to be relatively small due to space constraints, so the image files
will have to be equally small.
Three months from now SMSMobile
As of this writing, the J2ME contains the MIDP 1.0, but in a few months will upgrade to version 2.0, and with it
will come many new features, including vastly improved video game capabilities (Yes! Madden 2004 on your
cell phone!), full multimedia support on cell phones, and SMS message
capabilities.
Note: MIDP 2.0 features, including the SMS capability (also known as Wireless Messaging API)
are not yet in code release and are currently still part of the JCP. The code presented here is based on
the final standards API published on the JCP page.
Let's suppose that to enhance the BagTracMobile application, we add the following functionality:
At the check-in desk, the representative simply gives the passenger the official "BagTrac SMS Number" (in this example, the SMS number will be 21215557878), and that's it. The important things to note here are:
- The passenger never has to reveal his cell phone number.
- There is no code for the passenger to download. Every cell phone that has SMS messaging capabilities
will have native code already present on the phone to handle the sending and receiving of messages.
(Remember that nearly all cell phones sold today and all six major carriers have SMS capabilities, but some older phones might not.)
BagTrac SMS will then allow the passenger to request the baggage information simply by sending an
SMS message to the above number with their BagTrac number as the message:
Phone: 2125557878 Message: 20021030140701
The WMA also allows for server side handling of SMS messages. The company will set up a server running at
this address which will receive the messages and query DB2 for the information. It will then create an
SMS message with that information and send it back to the requesting phone. Again, no code is needed to
run this from the passenger's phone. The only code required sits on the server, so let's examine that:
String serverAddress = "sms://+2125557878";
MessageConnection connection = (MessageConnection)Connector.open(serverAddress);
while (true)
{
TextMessage message = (TextMessage)connection.receive();
String number = message.getPayloadText();
String location = Database.lookup(number);
Message.setPayloadText(location);
connection.send(message);
} |
The great thing about the SMS Message architecture is that when you receive a message, all the information to
return the call is already present in the Message object. The TextMessage object contains all the
information needed to send the response message back (the reason the passenger's cell phone number is
unnecessary). All you have to do is reset the text to the response from DB2 and send it back. Voila.
SMS messaging is a huge addition to J2ME and will allow for much more flexible and diverse cell phone
applications. Just from the brief example that follows, you can see the possibilities that SMS will present to
companies developing cell phone applications.
- The percentage of cell phones capable of using BagTrac SMS is currently much higher
than the percentage of those that can use BagTrac on J2ME-enabled cell phones.
- It's even foreseeable that SMS could replace HTTP connections as the communication method of choice
when developing client/server Java cell phone apps. SMS messages are cheap today; typical packages include
500 messages for US$2.99. Compare that with 1 Mb of data for $19.99 for normal HTTP connections. That averages
out to 1.1 cents per connection for SMS, and about 1.9 cents per connection over HTTP, or almost twice as much!
In conclusion
Just as we created a stand-alone HttpMobile class that handled all the client/server communication via
the HTTP protocol, we can also create a simple SMSMobile class that can handle client/server communication
via SMS protocol.
public static String doSMS(String address, String message)
{
MessageConnection connection = (MessageConnection)Connector.open(address);
TextMessage txtMessage = conn.newMessage(conn.TEXT_MESSAGE);
txtMessage.setPayloadText(message);
conn.send(txtMessage);
TextMessage responseMessage = (TextMessage)connection.receive();
return responseMessage.getPayloadText();
} |
The SMS portion of BagTrac has the potential to become much more popular than the downloadable J2ME
application. Most importantly, there is nothing to download and your phone doesn't need J2ME
support in order to use BagTrac SMS. It needs only SMS support, which every new phone sold today has.
Sending SMS messages is as simple as sending e-mail. In fact, more SMS messages than e-mails are sent daily throughout Europe. Also, SMS programs similar to this have already shown success in regions
that are far ahead of the U.S. in cell phone technology, such as Japan and, again, Europe.
Download | Description | Name | Size | Download method |
|---|
| Source code | wi-devosource.zip | 8 KB | HTTP |
|---|
Resources - Learn all about the the J2ME architecture for small networked devices from application developer Soma Ghosh. (developerWorks, November 2001)
- In another key article, Soma sheds light on MIDP as the fundamental foundation of J2ME programs. (developerWorks, March 2002)
- Test your applications by downloading the J2ME Toolkit.
- This white paper gives all the specs on MIDP 1.0 API. (PDF format)
- Supplement the info on MIDP 1.0 with these specs for the soon-to-be-released MIDP 2.0 API.
- A collection of informative articles addressing the topic of developing applications on J2ME is also at your disposal.
- You may be interested to read the Wireless Messaging API, or WMA, proposal. (PDF format)
- A list of the J2ME-compatible phones on the market is also available.
About the author  | 
|  |
Michael Abernethy works as a Java technology consultant for IBM in Austin, Texas, specializing in unique Java solutions to everyday situations. You can contact Mike at mabernet@us.ibm.com |
Rate this page
|  |