I’ve completed the JSR-179 Location API code for reverse geocoding in JavaME. This code essentially is an expansion of the previous JSR-179 example that i’ve posted in the blog before, plus the Reverse-Geocoding feature, thanks to TinyGeocoder service.

What this sample MIDlet does?
It obtain coordinates via the mobile phone JSR-179 Location API and subsequently display the name of the location using TinyGeocoder reverse geocoding service.
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.location.*;
import javax.microedition.io.*;
import javax.microedition.location.*;
import java.io.*;
public class Geocoder extends MIDlet implements CommandListener
{
public Display display;
public Form form;
private Command cmdExit,cmdOK;
public StringItem si, sili;
public Geocoder()
{
display =Display.getDisplay(this);
form = new Form("Location Api test");
cmdExit = new Command("Exit",Command.EXIT,5);
cmdOK = new Command("OK",Command.OK,1);
si = new StringItem("Coordinates", "Press OK");
sili = new StringItem("Location", "");
form.append(si);
form.append(sili);
form.addCommand(cmdOK);
form.addCommand(cmdExit);
form.setCommandListener(this);
}
public void startApp()
{
display.setCurrent(form);
}
public void pauseApp()
{}
public void destroyApp(boolean flag) {
notifyDestroyed();
}
public void commandAction(Command c, Displayable d)
{
if (c == cmdOK){
Retriever ret = new Retriever(this);
ret.start();
} else if (c == cmdExit) {
destroyApp(false);
}
}
public void displayString(String string)
{
si.setText(string);
}
public void showAlert(String message) {
Alert alert = new Alert("Alert",message,null,AlertType.WARNING);
display.setCurrent(alert,form);
}
}
class Retriever extends Thread {
private Geocoder midlet;
Form formRunning;
Gauge gauge;
public Retriever(Geocoder midlet)
{
/**
* Constructor
*
* EFFECTS: Initialise the server and store midlet information
*
* @param midlet The main application midlet
* @param server Forecast Server URL
*
*/
this.midlet = midlet;
formRunning = new Form("Retrieving Info");
formRunning.append(new Gauge("Processing",false,Gauge.INDEFINITE,Gauge.CONTINUOUS_RUNNING));
midlet.display.setCurrent(formRunning);
}
public void run()
{
/**
* Entry point of the thread
*
* EFFECTS: call to connect() method
*/
try {
checkLocation();
} catch (Exception ex)
{
ex.printStackTrace();
midlet.displayString(ex.toString());
} finally {
}
}
public void checkLocation() throws Exception
{
String string;
Location l;
LocationProvider lp;
Coordinates c;
// Set criteria for selecting a location provider:
// accurate to 500 meters horizontally
Criteria cr= new Criteria();
cr.setHorizontalAccuracy(5000);
cr.setVerticalAccuracy(5000);
// Get an instance of the provider
lp= LocationProvider.getInstance(cr);
// Request the location, setting a one-minute timeout
l = lp.getLocation(120);
c = l.getQualifiedCoordinates();
if(c != null ) {
// Use coordinate information
double lat = c.getLatitude();
double lon = c.getLongitude();
string = "\nLatitude : " + lat + "\nLongitude : " + lon;
new GetData(midlet,lat,lon).start();
} else {
string ="Location API failed";
}
formRunning.append("Obtained coordinates...");
midlet.displayString(string);
}
}
class GetData implements Runnable,CommandListener {
Geocoder midlet;
double lat, lon;
public GetData (Geocoder midlet, double lat, double lon) {
this.lat = lat;
this.lon = lon;
this.midlet = midlet;
}
public void commandAction (Command cmd,Displayable disp)
{
}
public void start() {
Thread t = new Thread(this);
t.start();
}
public void run() {
HttpConnection conn=null;
InputStream is=null;
String sb;
try {
String sUrl = "http://tinygeocoder.com/create-api.php?g="+""+lat+","+""+lon;
conn = (HttpConnection) Connector.open(sUrl,Connector.READ);
if (conn.getResponseCode() == HttpConnection.HTTP_OK) {
is = conn.openInputStream();
byte buf[] = new byte[128];
int total =0;
while (total < 128) {
int count = is.read(buf,total,128-total);
if (count<0) {
break;
}
total += count;
}
sb = new String(buf,0,total);
if (sb.length() < 10) {
midlet.showAlert("Connection error, please try again");
is.close();
conn.close();
return;
}
midlet.sili.setText(sb);
//midlet.form.append(sb);
//vectorized();
//midlet.saveCurrency(false,midlet.vector);
//midlet.display.setCurrent(midlet.form);
} else if (conn.getResponseCode() == HttpConnection.HTTP_NOT_FOUND) {
midlet.showAlert("URL not found");
} else {
midlet.showAlert("Server busy or unavailable. Please try again later");
}
} catch (SecurityException sex) {
midlet.showAlert("Connection failed. You need to authorize this application to access network");
} catch (IOException ioex) {
midlet.showAlert("Connection failed. Please try again later.");
} catch (Exception e){
midlet.showAlert(e.toString());
e.printStackTrace();
//midlet.display.setCurrent(midlet.form);
} finally {
try {
if (is != null) {
is.close();
}
if (conn != null) {
conn.close();
}
} catch (IOException ioexception) {}
is =null;
conn =null;
midlet.display.setCurrent(midlet.form);
}
}
public String URLEncode(String s)
{
if (s!=null) {
StringBuffer tmp = new StringBuffer();
int i=0;
try {
while (true) {
int b = (int)s.charAt(i++);
if ((b>=0x30 && b<=0x39) || (b>=0x41 && b<=0x5A) || (b>=0x61 && b<=0x7A)) {
tmp.append((char)b);
}
else {
tmp.append("%");
if (b <= 0xf) tmp.append("0");
tmp.append(Integer.toHexString(b));
}
}
}
catch (Exception e) {}
return tmp.toString();
}
return null;
}
}
The code requires mobile device which implements JSR-179 Location API and has been tested on Nokia E71 and 6210 Navigator.