Mobility

Exploring J2ME: Communication with the GCF

A mobile app that can't share its data is, well, useless. Find out how to enable remote communication in your J2ME applications.


Having an application run on a mobile device is really only useful if you have some facility for getting the information off the device into another nonmobile system. Handheld PCs like Palms have synchronization facilities built into them to make this possible, but what about other devices, such as a Java-enabled phone? The J2ME’s MIDP provides a set of classes in the javax.microedition.io package, collectively referred to as the Generic Connection Framework (GCF), that make programmatically transferring data to another machine very easy.

Exploring J2ME series
This is the final article in Builder.com’s "Exploring J2ME" series. You’ll find links to previous articles below.

Connecting with the world
The GCF is built around the concept of managed communication carried out by connection classes, each designed to manage a particular method of communication. The abstract Connection class (in fact, with only one defined method, it’s very abstract) serves as the base class for all connection management classes, which can in turn implement one of five interface classes to define their functionality. The intent behind this design is to make the GCF as generic and extensible as possible, while keeping it as easy to use as possible for the programmer.

The only connection type supported by MIDP 1.0 is HTTP, the protocol used to serve Web pages. HTTP support is provided by the HttpConnection class, which I’ll be concentrating on here. Being limited to HTTP isn’t as bad as it might sound at first. Your mobile app will, after all, be able to communicate with any Web server, and HttpConnection does a nice job of abstracting away the vagaries of managing a connection: There’s no fretting about with ports or other nonsense. You’ll need only a basic knowledge of the three kinds of HTTP requests to use it as a connection medium for your app.

A brief HTTP primer
Although an in-depth discussion of the mechanics of HTTP is beyond the scope of this article, suffice it to say that an HTTP client can send one of three messages to a server: GET, POST, and HEAD. Each request has a different meaning:
  • ·        A GET request is a request for data, such as a Web page or a multimedia file. You can also send data to the server with a GET request by including any data in the URL. Only relatively small amounts of data can be sent in this fashion, and of course the data encoded in the URL is plainly visible.
  • ·        A POST request sends data to a URL via an independent data stream. Submitting a Web form causes your browser to send a POST request. The Web server then extracts the data and passes it to the page or CGI program specified in the URL. You can send more data via a POST than a GET, and while it’s not truly secure, at least your data is not in plain sight.
  • ·        The final type of request is a HEAD request, which retrieves the metadata about a resource from the server. The reply from the server will not include the actual data requested, just information about it.

When a request from a client is received, the server sends a reply. The reply message is divided into a header and a body, which contains the actual requested data. The header includes, among other things, a status code indicating the success or failure of the request. A status code of 200 always means success, while 400 and over indicate an error.

Using HttpConnection
Now that we’re all grounded in HTTP basics, let’s see how you can use HttpConnection to request and receive data from a remote server. You open an HttpConnection using the static Connector class, which takes care of creating the object for you. After opening a connection, you set the type of client request you want to make, specifying one of HttpConnection.GET, HttpConnection.POST, or HttpConnection.HEAD:
 
http = (HttpConnection) Connector.open(“http://www.techrepublic.com”);
http.setRequestMethod(HttpConnection.GET);
 

The request is sent automatically to the URL you specify in Connector.open. You’ll then want to see if the request was successful by checking the getResponseCode method of HttpConnection:
 
if (http.getResponseCode() == HttpConnection.HTTP_OK){
   //success!
} else {
   //failure!
}
 

Actually sending and retrieving data once you have an open connection is simply a matter of opening the appropriate stream object using HttpConnection’s openInputStream and openOutputStream methods.

Retrieving data
Let’s look at a concrete example. In Listing A, I’ve placed the code for a sample MIDlet called CGFMidlet, which illustrates how to retrieve data over HttpConnection by reading the contents of a small text file hosted on a Web server. You may need to alter the URL (http://localhost/myfile.txt) to something sensible before running this sample.

Check out the getHTTPFile method, which takes care of actually retrieving the file. You can see that the HttpConnection makes a GET request for the file. After checking the response code to make sure everything’s okay, I read the contents of the file using an InputStream and display it on the MIDlet’s main form:
 
//Open an input stream to read the result
stream = http.openInputStream();
byte data[] = new byte[(int) http.getLength()];
stream.read(data);
//Set the result into the output field on the main form
output.setString(new String(data));

Sending data
You could also use a GET request to send data to the server, but this method has some disadvantages, which I alluded to earlier. To send large amounts of data, you’re better off using a POST instead. To see how to do that, check out the ServerConnection class in Listing B, written to allow the sample application I built during this series, ExpensesApp (download the source here), to send expenses to a server for storage. Things should look roughly similar, except that now I’m using HttpConnection.POST as the request type and setting a special message header to help the server handle the data in the request:
 
http.setRequestMethod(HttpConnection.POST);
//Content type property must be set
http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
//Open an output stream for the opened connection
OutputStream ostream = http.openOutputStream()
 

Next, I loop through an ExpenseInfo array and serialize each object into a string before sending its data to the server through an OutputStream:
 
for (int i=0; i<expensesRecords.length; i++) {
String s = ("ExpenseDate=" + expensesRecords[i].getDate().toString() +
"&ExpenseCategory=" + expensesRecords[i].getCategory() +
"&ExpenseAmount=" + String.valueOf(expensesRecords[i].getDollars()) + "." + String.valueOf(expensesRecords[i].getCents()) +
"&ExpenseDescription=" + expensesRecords[i].getDescription());
 

On the server side, you’ll need some kind of CGI-type process (an ASP, JSP, or Servlet, for example) running to accept the data. Each identifier and value pair in the string will appear to the receiving page to be a control from a submitted form, so your receiving page will access the data just as it would access form data.

While HTTP may not be the ideal choice for transmitting large amounts of data, it’s flexible enough to get the job done, and the GCF makes using it remarkably simple. With any luck, future versions will include more options for the developer.

 

 

Editor's Picks