| By Jason R Briggs | Article Rating: |
|
| August 1, 2001 12:00 AM EDT | Reads: |
16,258 |
In Part 1 of this article, which can be found in JDJ (Vol. 6, issue 7), we covered the basics of creating a Mobile Information Device Profile application (also called a MIDlet). We covered some of the functionality available in the user interface packages and a slightly more advanced graphics example.
Missing from that discussion was one of the more unusual APIs included in MIDP - the Record Management System - which can be found in the package javax.microedition.rms. This is a persistent storage system based on a "simple record-oriented database." If you want to store data on a device (and not on the server, for example), you'll need to become very familiar with RMS.
The most fundamental object in RMS is the javax.microedition.rms.RecordStore, which is owned by a particular suite of applications currently installed on the device. What this means is that all the applications in the suite can share the same data, if necessary - games, for example, can store their saved state in one RecordStore. A phone book application might share its data with a simple scheduling application - as long as it's in the same suite, of course.
To open (or create) a new RecordStore, use a static method found in the RecordStore class. Assuming we wanted to write a Phone Book MIDlet, we would probably call our store "PhoneBook".
RecordStore store = RecordStore.openRecordStore("PhoneBook",true);The Boolean value "true" is used to specify that the store will be created, if necessary.
A RecordStore has a number of methods that can be applied to it. The most useful of these are:
- addRecord(...): Add a new record to the store
- deleteRecord(...): Delete a record from the store
- getNumRecords(...): Get the number of records in the store
- getRecord(...): Get a copy of data in a record
- getSize(): Get the size of the record store (in bytes)
- getSizeAvailable(): Get the available space for the store to grow (also in bytes)
- setRecord(...): Set the data in a specified record
Use a RecordEnumeration to move back and forth through the store and view the data:
RecordEnumeration recordEnum = store.enumerateRecords(null, pbcomp, false);Where the first argument (null) is the filter that specifies the subset of records that will be enumerated, the second argument (pbcomp) is a Record- Comparator (more on that soon) that specifies the order, and the final argument (false) specifies that the enumeration will, in this case, not be kept up-to-date with the contents of the store (in other words, the enumeration is a copy of the store at that point).
A RecordComparator, as mentioned before, is used to order an enumeration. Create a comparator by implementing the RecordComparator interface. The interface describes a single method (compare) that returns an integer value depending upon whether the contents of one byte array FOLLOWS, PRECEDES, or is EQUIVALENT to a second byte array (see Listing 1). Listings 1-7 can be found on the JDJ Web site, www.javadevelopersjournal.com. Now that we have an enumeration of records, what can we do with it? The important methods in the RecordEnumeration are:
- hasNextElement(): Does the enumeration have more elements?
- hasPreviousElements(): Are there elements prior to the current position?
- nextRecord(): Get a copy of the data in the next record
- nextRecordId(): Get the recordId of the next record
- numRecords(): Get the number of records in the enumeration
- PreviousRecord(): Get a copy of the data in the previous record
- PreviousRecordId(): Get the recordId of the previous record
public void keyPressed(int k) {In the parent class (in this case the MIDlet), the processAction() method will move forward and backward in the enumeration depending upon whether the up or down arrow has been pressed. For example:
parent.processAction(getGameAction(k));
}
if (action == Canvas.UP && recordEnum.hasPreviousElement()) {In this case, currentRecordID is an int that holds the recordId the enumeration is currently pointing to, and set(...) is a user-defined method that calls the canvas and changes the display accordingly.
currentRecordID = recordEnum.previousRecordId();
set(store.getRecord(currentRecordID));
}
else if (action == Canvas.DOWN && recordEnum.hasNextElement()) {
currentRecordID = recordEnum.nextRecordId();
set(store.getRecord(currentRecordID));
}
Listing 2 provides the full method source; Listing 3 provides the source of the canvas class.
Large Mouthfuls, or Multiple Bytes
The records in a store are byte arrays, meaning you store and retrieve your records as simple byte arrays. So you can either work with the raw bytes (as I've done in my PhoneBook application, for simplicity's sake), or use a combination of ByteArray and data streams. Obviously, unless you have a requirement for fixed data sizes (which is inefficient, but again that's what I'm using in the PhoneBook), the stream combination will probably be the more efficient way to go, in terms of the most effective use of storage space.
It has the added advantage that using the various read methods in a DataInputStream (for example, readInt, readLond, readShort, readUTF), keep you one step away from the messy details of how that data is actually stored in the byte array.
To use the stream combination, you'll probably do something like the following:
ByteArrayOutputStream baos = new ByteArrayOutputStream();In comparison, the save() method in PhoneBook.java uses a fixed length name and variable length phone number, creating byte-arrays of the data using a specially defined function called rpad (which adds spaces on the end of the name if it's not long enough) (see Listing 4).
DataOutputStream dos = new DataOutputStream (baos);
dos.writeUTF("Hello");
dos.writeUTF("Test");
dos.writeInt(100);byte rec[] = baos.toByteArray();
I leave it up to the individual to decide which way works better for them. One of the joys of Java is that while it provides functionality to insulate developers from any "nastiness," it also allows you to get in there and "do things your own way."
Figures 1-3 show the main screens in the PhoneBook MIDlet.
Networking: It's More than Making
Friends and Influencing People
MIDP has to include networking support. A large number of Java developers in lynch-mode, with nooses made from coaxial cable and baseball bats molded out of melted-down network cards, would turn up on Sun's doorstep in Palo Alto baying for blood if a Java product was released without adequate network support, and Sun knows that. Accordingly, you can find the various network IO classes in the javax.microedition.io package. However, network connectivity is handled differently from what you might be used to in the Standard Edition of Java (in java.net.*). One major difference is that instead of creating/opening a socket or a URLConnection and then getting an input stream from that object, you use the Connector class to create and open a Connection, an Input/OutputStream, or a DataInput/DataOutputStream. For example:
HttpConnection c = (HttpConnection)Connector.open("http://.................");There are a number of Connection interfaces defined in javax.microedition.io: Connection, ContentConnection, DatagramConnection, HttpConnection, InputConnection, OutputConnection, StreamConnection and StreamConnectionNotifier.
In Listing 5 we'll look at the HttpConnection interface using a MIDlet called HttpTest.java. In this application we'll define a test method that takes a URL string as a parameter and then opens an HTTP POST connection to that URL (for more information on HTTP see RFC 2616 - www.ietf.org/rfc/rfc2616.txt?number=2616).
Looking at Listing 5 line by line: Lines 1 and 2 declare the HttpConnection object and the InputStream. Line 5 opens an HttpConnection to the supplied URL. Line 6 sets the request method on the connection. In this case we want to perform HTTP POST operations. Line 8 opens an input stream to the connection. Line 10 tries to get the content length. If a content length is provided, lines 12 and 13 create a byte array and then read from the stream into the array. If no length was provided, lines 18-22 read from the stream, character by character, until a terminator is reached. Lines 15 and 23 return the result from either set of operations. Finally, lines 27-30 and 32-35 close the InputStream and Connection.
I think you'll agree that this is fairly painless networking (as with most communications in Java).
What else is included in this MIDlet? HttpTest creates a simple list of five tests that's used as the first screen the user sees. When the user selects a test, and then selects the OK command, the code in Listing 6 is executed.
In Listing 6 lines 2-5 destroy the application if the Exit command was selected. Line 7 checks the current state, which is used to switch between the two screens, and line 8 changes the display to a TextBox (tb), which will be used to show the output. Line 11 gets the currently selected index in a list of tests that can be executed. Line 13 checks that the test selected is valid. Line 14 calls the test method with the URL of a TestServlet and passes a parameter action, which will be in the form, http://localhost:8080/servlet/TestServlet?action=n (n being the numbers 1-5, depending upon the user's selection). Lines 16-18 check that the test method returned a valid result, and assigns that result to the output TextBox, using the setString(...) method. Finally, lines 26-28 change the display back to the list of available tests.
It Takes Two
One other thing is missing from this network conversation - Test-
Servlet.java, shown in Listing 7. This is not the right place for a deep and meaningful discussion on servlet development, but to summarize what the servlet is doing:
- A doPost event arrives to be handled by the servlet.
- The servlet gets the writer for the ServletResponse object.
- The content type of the response is set.
- The parameter "action" value is retrieved from the ServletRequest.
- The parameter is converted to an int, and the word "test" is appended to a string a number of times based upon that number.
- Finally, the number is concatenated on the end of the string, and the result is written out using the writer.
Summary
We've now covered the major parts of creating MIDP applications. In Part 3, we'll put all the pieces together extending the PhoneBook application already created. We'll retrieve data using an EJB, and funnel it through a servlet and into our J2ME front end.
Published August 1, 2001 Reads 16,258
Copyright © 2001 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By Jason R Briggs
As well as being a contributing editor for Java Developers Journal, Jason R Briggs is a Java programmer and Development Manager for a wireless technology company, based in Auckland, New Zealand.
- Patterns for Building High Performance Applications
- It's the Java vs. C++ Shootout Revisited!
- Asynchronous Logging Using Spring
- Java for Programmers (2nd Edition)
- Cross-Platform Mobile Website Development – a Tool Comparison
- Three Buzzwords That Every CIO Hears but One They Should Listen To
- Write Once Run Anywhere or Cross Platform Mobile Development Tools
- Immersing into JavaScript Frameworks
- Workday Reportedly Prepping to Go Public
- Cloud Expo New York: The Java EE 7 Platform - Developing for the Cloud
- Book Review: Sams Teach Yourself Java in 24 Hours
- OpenOffice.com Lives
- Book Excerpt: Introducing HTML5
- Adobe Sends Flex to the Apache Foundation
- Five Years Waiting for JRE 7: Is It Justified? (Part 1)
- Book Excerpt: Java Application Profiling Tips and Tricks
- i-Technology in 2012: Five Industry Predictions
- Patterns for Building High Performance Applications
- It's the Java vs. C++ Shootout Revisited!
- OpenXava 4.3: Rapid Java Web Development
- The Next Web Architecture
- Asynchronous Logging Using Spring
- Java for Programmers (2nd Edition)
- Is Write Once Run Anywhere Ever Going to Be a Reality?
- A Cup of AJAX? Nay, Just Regular Java Please
- Java Developer's Journal Exclusive: 2006 "JDJ Editors' Choice" Awards
- JavaServer Faces (JSF) vs Struts
- The i-Technology Right Stuff
- Rich Internet Applications with Adobe Flex 2 and Java
- Java vs C++ "Shootout" Revisited
- Bean-Managed Persistence Using a Proxy List
- Reporting Made Easy with JasperReports and Hibernate
- Creating a Pet Store Application with JavaServer Faces, Spring, and Hibernate
- Why Do 'Cool Kids' Choose Ruby or PHP to Build Websites Instead of Java?
- What's New in Eclipse?
- i-Technology Predictions for 2007: Where's It All Headed?























