Accessing a Resource over HTTP

By C. Enrique Ortiz

The Hypertext Transport Protocol (HTTP) is a very important application-level network protocol. Most of the access to web resources, including web pages, Extensible Markup Language (XML) documents, images, ringtones, wallpapers, and web services all occur over HTTP.

The Mobile Information Device Profile (MIDP) provides HTTP support via the Generic Connection Framework (GCF) HttpConnection, which provides methods to GET and POST resources over HTTP, read and write HTTP headers, and different methods to read and write the resource, for example, as a stream or a byte array.

In this technical tip, I introduce a helper class, NetworkUtils, that defines a number of HTTP constants and a helper method that uses an HttpConnection to connect to a server over HTTP, get a resource, and return it as a DataInputStream.

Class NetworkUtils defines various HTTP and MIME-type constants, and the static method getResourcetOverHTTP() to connect to a server over HTTP and retrieve the named resource. The method returns a DataInputStream that can be used to read the content stream in any way you wish.

/\*
\* NetworkUtils.java
\*
\* Network Utilities. A simple method to get a resource over
\* HTTP and return a DataInputStream is provided.
\*/

package com.j2medeveloper.com.ttips.utils;

import java.io.IOException;
import java.io.DataInputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;

/\*\*
\* Various network utilities. A simple method to get a resource over
\* HTTP and return a DataInputStream is provided.
\*
\* @author C. Enrique Ortiz
\*/
public class NetworkUtils {

/////////////////////////////////////////////////////////////////
// MIME Types
/////////////////////////////////////////////////////////////////
public static final String MIMETYPE_TEXT_PLAIN = "text/plain";
public static final String MIMETYPE_TEXT_XML = "text/xml";
public static final String MIMETYPE_APP_XML = "application/xml";
public static final String MIMETYPE_IMAGE_PNG = "image/png";

/////////////////////////////////////////////////////////////////
// HTTP Contants
/////////////////////////////////////////////////////////////////
private static final String HTTPHDR_ACCEPT = "Accept";

private static final String HTTPHDR_USER_AGENT = "User-Agent";
private static String HTTPHDR_USER_AGENT_VALUE;

private static final String HTTPHDR_CONNECTION = "Connection";
private static final String HTTPHDR_CONNECTION_CLOSE = "close";

private static final String HTTPHDR_CACHE_CONTROL = "Cache-Control";
private static final String HTTPHDR_CACHE_CONTROL_NOTRANSFORM =
"no-transform";
private static final String HTTPHDR_CONTENT_LEN = "Content-Length";

static {
// Retrieve the underlying profile and configuration for User Agent
String p = System.getProperty("microedition.profiles");
String c = System.getProperty("microedition.configuration");
HTTPHDR_USER_AGENT_VALUE = "Profile/" + p + " Configuration/" + c;
}

/\*\*
\* Gets a Resource over HTTP, returing an <code>DataInputStream</code> to it
\*
\* @param uri is the URI to use to get the resource to retrieve
\* @pararm mimeType is the (possible) mime type(s) of the resource to retrieve
\*
\* @return an <code>DataInputStream</code> for the input resource
\*
\* @throws <code>IOException</code> is thrown if an error is encountered
\*/
static public DataInputStream getResourceOverHTTP(
String uri,
String mimeType) throws IOException {

HttpConnection connection = null;
IOException ioException = null;
DataInputStream is = null;

try {
connection = (HttpConnection) Connector.open(uri, Connector.READ, true);

connection.setRequestMethod(HttpConnection.GET);

connection.setRequestProperty(
HTTPHDR_ACCEPT,
mimeType);

connection.setRequestProperty(
HTTPHDR_USER_AGENT,
HTTPHDR_USER_AGENT_VALUE);

connection.setRequestProperty(
HTTPHDR_CONNECTION,
HTTPHDR_CONNECTION_CLOSE);

connection.setRequestProperty(
HTTPHDR_CACHE_CONTROL,
HTTPHDR_CACHE_CONTROL_NOTRANSFORM);

connection.setRequestProperty(
HTTPHDR_CONTENT_LEN,
String.valueOf("0"));

//////////////////////////////////////
// Send GET, receive initial response
//////////////////////////////////////
int rc = connection.getResponseCode();

/////////////////////////////////////////////////////////
// If an HTTP error was encountered, stop, indicate error
/////////////////////////////////////////////////////////
if (rc != HttpConnection.HTTP_OK) {
// Log error, throw IO exception
ioException = new IOException("Http Error, response Code is " + rc);
throw ioException;
}
is = connection.openDataInputStream();
} catch (IOException ioe) {
// Log error, throw IO exception
throw ioe; // Propagate the IO Exception
} finally {
if (connection != null) connection.close();
return is;
}
}
}

The method opens an HTTP connection to the specified Uniform Resource Identifier (URI), sets the HTTP request headers to indicate the accepted MIME types, the user-agent, the connection persistence to not persist, and the cache control option to tell proxies not to transform or compress the content. The GET request is sent to the server by calling method getResponseCode(). If no error is encountered, a DataInputStream is returned, and passed back to the caller, otherwise and IOException is thrown.

To use this utility class and its static method getResourceOverHTTP(), all you have to do is provide the URI to the resource on the web, and its MIME type. If successful, the method will return a DataInputStream to the resource, or throw an IOException that must be handled. Remember that all network operations should be dispatched in a separate thread of execution to avoid blocking other threads, and to close streams when done using them:

public final class MyClass implements Runnable {
:
private String thPngUri; // URI used by thread
:


/\*\*
\* Dispatches the thread to retrieve the resource over HTTP
\*
\* @param uri the URI to the resource
\*/
private void dispatchGetResourceTh(String uri) {
thPngUri = uri; // set class-wide member, that is used by thread
Thread th = new Thread(this);
th.start();
}

:

/\*\*
\* Thread of execution
\*/
public void run() {
DataInputStream is = null;
try {
is = NetworkUtils.getResourceOverHTTP(
thPngUri, NetworkUtils.MIMETYPE_IMAGE_PNG);
} catch (IOException ioe) {
// Log error, exit
return;
}
notifyRetrievalComplete(thUri, is);
}
}

Once method getResourceOverHTTP() returns successfully with the DataInputStream to the resource, the method notifyRetrievalComplete() is called to further process the resource, for example, if the resource is an image, to create an Image from the DataInputStream:

private void notifyRetrievalComplete (
String resourceName, DataInputStream is) {
:

// Create an Image from the DataInputStream.
Image image = Image.createImage(is);
:

// Close the stream when done
is.close();
:
}
private static String mimeType = "audio/midi";
:

private void notifyRetrievalComplete (
String resourceName, DataInputStream is) {

// Create a Player to play back media from the DataInputStream.
Player myPlayer = Manager.createPlayer(is, mimeType)
:

// Close the stream when done
is.close();
:
}
Conclusion

This technical tip introduced a simple method that MIDlets can use to retrieve a resource over HTTP in the form of a DataInputStream. The DataInputStream could represent various data types such as an image, XML document, or a video stream that can read the application and process it accordingly. You can extend this class with more MIME types, and with other helper methods, for example, a method to retrieve the resource as a byte array, or a more sophisticated send/receive method.

Comments:

Nice tips but do you have some idea if the user cancel the communication?

best regards

Posted by Javier on October 14, 2007 at 01:25 PM PDT #

Thanks, this solve an issue I have with connections.
What if communications is broken, any sort of recovery?

Posted by Miguel Barba on October 16, 2007 at 03:14 AM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Tips for developers who use Java technologies (Java SE, Java ME, JavaFX) for mobile and embedded devices.

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today