ads

JavaME JSR-179 Example Code : Detect Location via TinyGeocoder

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.

J2ME GPS Reverse Geocoding mypapit

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.

JAVA:
  1. import javax.microedition.midlet.*;
  2. import javax.microedition.lcdui.*;
  3. import javax.microedition.location.*;
  4. import javax.microedition.io.*;
  5. import javax.microedition.location.*;
  6. import java.io.*;
  7.  
  8. public class Geocoder extends MIDlet implements CommandListener
  9. {
  10.     public Display display;
  11.     public Form form;
  12.     private Command cmdExit,cmdOK;
  13.     public StringItem si, sili;
  14.  
  15.     public Geocoder()
  16.     {
  17.  
  18.         display =Display.getDisplay(this);
  19.         form = new Form("Location Api test");
  20.         cmdExit = new Command("Exit",Command.EXIT,5);
  21.         cmdOK = new Command("OK",Command.OK,1);
  22.         si = new StringItem("Coordinates", "Press OK");
  23.         sili = new StringItem("Location", "");
  24.         form.append(si);
  25.         form.append(sili);
  26.         form.addCommand(cmdOK);
  27.         form.addCommand(cmdExit);
  28.         form.setCommandListener(this);
  29.     }
  30.  
  31.     public void startApp()
  32.     {
  33.         display.setCurrent(form);
  34.     }
  35.  
  36.  
  37.     public void pauseApp()
  38.     {}
  39.  
  40.     public void destroyApp(boolean flag) {
  41.         notifyDestroyed();
  42.     }
  43.  
  44.     public void commandAction(Command c, Displayable d)
  45.     {
  46.         if (c == cmdOK){
  47.             Retriever ret = new Retriever(this);
  48.             ret.start();
  49.  
  50.         } else if (c == cmdExit) {
  51.             destroyApp(false);
  52.         }
  53.     }
  54.  
  55.     public void displayString(String string)
  56.     {
  57.         si.setText(string);
  58.     }
  59.  
  60.     public void showAlert(String message) {
  61.         Alert alert = new Alert("Alert",message,null,AlertType.WARNING);
  62.         display.setCurrent(alert,form);
  63.     }
  64.  
  65.  
  66.  
  67.  
  68. }
  69.  
  70. class Retriever extends Thread {
  71.  
  72.     private Geocoder midlet;
  73.     Form formRunning;
  74.     Gauge gauge;
  75.  
  76.  
  77.  
  78.     public Retriever(Geocoder midlet)
  79.         {
  80.             /**
  81.               * Constructor
  82.               *
  83.               * EFFECTS: Initialise the server and store midlet information
  84.               *
  85.               * @param midlet The main application midlet
  86.               * @param server Forecast Server URL
  87.               *
  88.               */
  89.             this.midlet = midlet;
  90.             formRunning = new Form("Retrieving Info");
  91.             formRunning.append(new Gauge("Processing",false,Gauge.INDEFINITE,Gauge.CONTINUOUS_RUNNING));
  92.             midlet.display.setCurrent(formRunning);
  93.  
  94.     }
  95.  
  96.     public void run()
  97.         {
  98.             /**
  99.             * Entry point of the thread
  100.             *
  101.             * EFFECTS: call to connect() method
  102.             */
  103.             try {
  104.                             checkLocation();
  105.                         } catch (Exception ex)
  106.                         {
  107.                             ex.printStackTrace();
  108.                             midlet.displayString(ex.toString());
  109.             } finally {
  110.  
  111.             }
  112.  
  113.  
  114.         }
  115.  
  116.     public void checkLocation() throws Exception
  117.     {
  118.         String string;
  119.         Location l;
  120.         LocationProvider lp;
  121.         Coordinates c;
  122.         // Set criteria for selecting a location provider:
  123.         // accurate to 500 meters horizontally
  124.         Criteria cr= new Criteria();
  125.         cr.setHorizontalAccuracy(5000);
  126.         cr.setVerticalAccuracy(5000);
  127.  
  128.         // Get an instance of the provider
  129.         lp= LocationProvider.getInstance(cr);
  130.  
  131.         // Request the location, setting a one-minute timeout
  132.         l = lp.getLocation(120);
  133.         c = l.getQualifiedCoordinates();
  134.  
  135.         if(c != null ) {
  136.           // Use coordinate information
  137.           double lat = c.getLatitude();
  138.           double lon = c.getLongitude();
  139.           string = "\nLatitude : " + lat + "\nLongitude : " + lon;
  140.           new GetData(midlet,lat,lon).start();
  141.  
  142.         } else {
  143.             string ="Location API failed";
  144.         }
  145.  
  146.         formRunning.append("Obtained coordinates...");
  147.         midlet.displayString(string);
  148.     }
  149. }
  150.  
  151. class GetData implements Runnable,CommandListener {
  152.  
  153. Geocoder midlet;
  154. double lat, lon;
  155.  
  156. public GetData (Geocoder midlet, double lat, double lon) {
  157.  
  158.     this.lat = lat;
  159.     this.lon = lon;
  160.     this.midlet = midlet;
  161.  
  162.  
  163. }
  164.  
  165. public void commandAction (Command cmd,Displayable disp)
  166. {
  167.  
  168. }
  169.  
  170. public void start() {
  171.        Thread t = new Thread(this);
  172.        t.start();
  173. }
  174.  
  175.  
  176. public void run() {
  177.     HttpConnection conn=null;
  178.     InputStream is=null;
  179.     String sb;
  180.  
  181.     try {
  182.             String sUrl = "http://tinygeocoder.com/create-api.php?g="+""+lat+","+""+lon;
  183.             conn = (HttpConnection) Connector.open(sUrl,Connector.READ);
  184.             if (conn.getResponseCode() == HttpConnection.HTTP_OK) {
  185.                     is = conn.openInputStream();
  186.                     byte buf[] = new byte[128];
  187.                     int total =0;
  188.                     while (total <128) {
  189.                         int count = is.read(buf,total,128-total);
  190.                         if (count<0) {
  191.                             break;
  192.                         }
  193.                         total += count;
  194.                     }
  195.  
  196.                     sb = new String(buf,0,total);
  197.  
  198.                     if (sb.length() <10) {
  199.                             midlet.showAlert("Connection error, please try again");
  200.                             is.close();
  201.                             conn.close();
  202.  
  203.                             return;
  204.                     }
  205.  
  206.                       midlet.sili.setText(sb);
  207.                     //midlet.form.append(sb);
  208.                     //vectorized();
  209.                     //midlet.saveCurrency(false,midlet.vector);
  210.                     //midlet.display.setCurrent(midlet.form);
  211.             } else if (conn.getResponseCode() == HttpConnection.HTTP_NOT_FOUND) {
  212.                     midlet.showAlert("URL not found");
  213.  
  214.             } else {
  215.                 midlet.showAlert("Server busy or unavailable. Please try again later");
  216.             }
  217.  
  218.     } catch (SecurityException sex) {
  219.         midlet.showAlert("Connection failed. You need to authorize this application to access network");
  220.     } catch (IOException ioex) {
  221.             midlet.showAlert("Connection failed. Please try again later.");
  222.     } catch (Exception e){
  223.         midlet.showAlert(e.toString());
  224.         e.printStackTrace();
  225.         //midlet.display.setCurrent(midlet.form);
  226.     } finally {
  227.         try {
  228.             if (is != null) {
  229.                 is.close();
  230.             }
  231.  
  232.             if (conn != null) {
  233.                 conn.close();
  234.             }
  235.         } catch (IOException ioexception) {}
  236.             is =null;
  237.             conn =null;
  238.             midlet.display.setCurrent(midlet.form);
  239.  
  240.  
  241.     }
  242. }
  243.  
  244.  
  245. public String URLEncode(String s)
  246. {
  247.         if (s!=null) {
  248.             StringBuffer tmp = new StringBuffer();
  249.             int i=0;
  250.             try {
  251.                 while (true) {
  252.                     int b = (int)s.charAt(i++);
  253.                     if ((b>=0x30 && b<=0x39) || (b>=0x41 && b<=0x5A) || (b>=0x61 && b<=0x7A)) {
  254.                         tmp.append((char)b);
  255.                     }
  256.                     else {
  257.                         tmp.append("%");
  258.                         if (b <= 0xf) tmp.append("0");
  259.                         tmp.append(Integer.toHexString(b));
  260.                     }
  261.                 }
  262.             }
  263.             catch (Exception e) {}
  264.             return tmp.toString();
  265.         }
  266.         return null;
  267. }
  268. }

The code requires mobile device which implements JSR-179 Location API and has been tested on Nokia E71 and 6210 Navigator.

Kirodict – a Compact, Lightweight JavaME mobile dictionary

Finally after spending a couple months working on this on and off personal project, I decided to release the final version of Kirodict - a lightweight mobile dictionary.

As it name implies, Kirodict was designed to be small in size while maintaining its functionality as a fully fledge dictionary for mobile and embedded device. Kirodict acts as a front-end to an RFC2229 (dict.org) compatible server which it obtain the word definition from.

Kirodict - compact mobile dictionary

Its small and compact size as well as its portability makes it an attractive application to be downloaded and installed on your mobile phone. Kirodict requires mobile phones with at least these feature :

  • MIDP 2.0 /CLDC 1.0 compatible phones
  • 128kB of free storage space
  • Phone with network connection (3G, GPRS, Wifi, wimax)

With lower requirements, it can be installed on a lower end phone without much problem. Kirodict does not use additional storage space as it does not cache its results.

Kirodict can be downloaded from Kirodict Google Code project website and it is licensed under the GNU General Public License version 2.0