Monday, April 5, 2010

Reverse Geocoding in android 2.2 Froyo(or api level greater than 8)

I have faced problem in android 2.2 Froyo(or api level greater than 8) and found solution myself.
getFromLocationName() returns null or get java.io.IOException: Service not Available
exception so i have find alternate solution to solve this issue.

Google provide service for reverse Geocoding just use this service for reverse geocoding in api level 8 or greater.
below is sample code:
Firstly add kxml.jar into your project using project->Build Path
For download kxml.jar click here.

now create below class into your project.
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Hashtable;
import org.kxml.*;
import org.kxml.io.*;
import org.kxml.kdom.*;
import org.kxml.parser.*;
import android.util.Log;

public class Geocoding
{
      Hashtable ht=null;
      private boolean time=true;
      private int count=0;
      private String citystreetvalue=null;
      public Geocoding()
      {
           System.out.println("Constructor call...");
           ht=new Hashtable();
      }
//***************************** Find Address of the latitude Longitude ***********

      public String parseXml(String address)
      {
         try
         {
            System.out.println("Address is:" + address);
            //URL mUrl = new URL("http://maps.google.com/maps/api/geocode/xml?address=tagore%20road%20rajkot&sensor=false");

            URL mUrl = new URL("http://maps.google.com/maps/api/geocode/xml?address=" + address + "&sensor=false");

             Log.e("Url",mUrl.toString());
             HttpURLConnection mConn = (HttpURLConnection) mUrl.openConnection();
             System.out.println("After address add...");
             InputStream is = mConn.getInputStream();
             Reader reader = new InputStreamReader(is);
             XmlParser parser = new XmlParser(reader);
             traverse(parser,"");
             mConn.disconnect();
             is.close();
             System.out.println("Close all connection...");
             if(ht.get("status").toString().equals("OK"))
             {
                System.out.println("result is Ok..." + ht.get("locality").toString() + ht.get("street").toString());
                 citystreetvalue=ht.get("latitude").toString() + ","+ ht.get("longitude").toString() +","+ht.get("street").toString()+","+ht.get("locality").toString();
             }else
             {
                  System.out.println("result is not Ok...");
                  citystreetvalue="InvalidLocation";
             }
           }
           catch(Exception e)
           {
               System.out.println(e.toString());
           }
           System.out.println("before returen statement...");
        return citystreetvalue;
    }
    public void traverse(XmlParser parser, String indent ) throws Exception
    {
        System.out.println("in Traverse method....");
        boolean leave = false;
        String title = new String();
        String desc = new String();
        do
        {
           ParseEvent event = parser.read ();
           ParseEvent pe;
           switch (event.getType())
           {
               // For example,
               case Xml.START_TAG:
               // see API doc of StartTag for more access methods
               // Pick up Title for display
                     if ("status".equals(event.getName()))
                     {
                           pe = parser.read();
                           title = pe.getText();
                           ht.put("status",title);
                     }
                     if(count<2 br="br">
                     {
                         if ("lat".equals(event.getName()))
                         {
                             pe = parser.read();
                             title = pe.getText();
                             ht.put("latitude",title);
                             count=count+1;
                         }
                         if ("lng".equals(event.getName()))
                         {
                             pe = parser.read();
                             desc = pe.getText();
                             ht.put("longitude",desc);
                             count=count+1;
                         }
                     }
                     if ("long_name".equals(event.getName()))
                     {
                        pe = parser.read();
                        title = pe.getText();
                     }
                     if ("type".equals(event.getName()))
                     {
                        pe = parser.read();
                        desc = pe.getText();
                        if(desc.equals("route"))
                        {
                            System.out.println("street is:" + title);
                            ht.put("street",title);
                        }
                     }
                     if("formatted_address".equals(event.getName()))
                     {
                        if(time)
                        {
                            pe = parser.read();
                            title = pe.getText();
                            ht.put("address",title);
                            time=false;
                        }
                     }
                     ht.put(desc,title);
                     traverse(parser,"") ; // recursion call for each
                     break;
                    // For example 
               case Xml.END_TAG:
                    leave = true;
                    break;
               // For example
               case Xml.END_DOCUMENT:
                    leave = true;
                    break;

              // For example, the text between tags
               case Xml.TEXT:
                    break;
     
               case Xml.WHITESPACE:
                    break; 
    
              default:
          }
       } while( !leave );
   }
}


And now your activity class is as below.


import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Vector;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TabHost;
import android.widget.TabHost.TabSpec;

public class GeocoderAppActivity extends MapActivity {
 /** Called when the activity is first created. */
 MapView mapview;
 MapController mpcontroller;
 LocationManager locationmngr;
 LinearLayout googlemap_panel; 
 EditText addresstxt;  
 Geocoding geocoding=null;
  
 
 @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        addresstxt=(EditText)findViewById(R.id.editText1);
        addresstxt.setText("");
        addresstxt.setOnKeyListener(SearchListner);
        
        googlemap_panel=(LinearLayout)findViewById(R.id.googlemap_panel);
               
        mapview = new MapView(this, "0b2ibhsKaC5aNXBVdm-c6uJZVPbiypSmaMppgUg");
        mapview.setVisibility(View.VISIBLE);
        mapview.setClickable(true);
        mapview.setEnabled(true);
        
        mapview.setSatellite(true);
  View zoomControll=mapview.getZoomControls();
  mapview.addView(zoomControll);
  mapview.displayZoomControls(true);
  
  
  String loccontax=Context.LOCATION_SERVICE;
  locationmngr=(LocationManager)getSystemService(loccontax);
              
  mpcontroller=mapview.getController();
  
  Double latitude=22.287535*1E6;
  Double longitude=70.791226*1E6;      
  
  GeoPoint gp=new GeoPoint(latitude.intValue(),longitude.intValue());
  mpcontroller.setCenter(gp);
  mpcontroller.setZoom(18);
  mpcontroller.animateTo(gp);        
        
    }
 @Override
 protected boolean isRouteDisplayed() {
  // TODO Auto-generated method stub
  return false;
 }
 private android.view.View.OnKeyListener SearchListner = new View.OnKeyListener() {
  
  @Override
  public boolean onKey(View v, int keyCode, KeyEvent event) {
   
   if ((event.getAction()==KeyEvent.ACTION_DOWN)&&(keyCode == KeyEvent.KEYCODE_ENTER)){
    
    String txtvalue=addresstxt.getText().toString().trim();
    
    googlemap_panel.removeView(mapview);
    googlemap_panel.addView(mapview, new LayoutParams(android.view.ViewGroup.LayoutParams.FILL_PARENT, android.view.ViewGroup.LayoutParams.FILL_PARENT));
          
    rgeocoding(txtvalue);     
    
      }
   return false;
  }
 };
 
 public void rgeocoding(String addres)
 {
  geocoding=new Geocoding();

  Log.e("girish", addres);
  StringBuilder sb=new StringBuilder("Address:");
  
  
  addres=addres.replace(" ","%20");
  
  String citystreetvalue=geocoding.parseXml(addres);    
  System.out.println("string is:" + citystreetvalue);
  
  
  if(citystreetvalue.equals("InvalidLocation"))
  {
   showDialog("Invalide Location...");
   
  }else
  {                 
   String citystreetval[]=Split(citystreetvalue, ",");  
         String latcity=citystreetval[3];
         String latstreet=citystreetval[2];
         String nlatitude=citystreetval[0];
         String nlongitude=citystreetval[1];
         
        
         Log.e("lat is:", nlatitude);
         Log.e("long is:", nlongitude);
            
         sb.append(latstreet);
         sb.append(latcity);
   sb.append(nlatitude);
   sb.append(nlongitude);
   
   Log.e("String is:" , sb.toString());
   
   Double latitude=Double.parseDouble(nlatitude);
   Double longitude=Double.parseDouble(nlongitude);
   
   
     GeoPoint gp=new GeoPoint(latitude.intValue(),longitude.intValue());
     mpcontroller.setCenter(gp);
     mpcontroller.setZoom(18);
     mpcontroller.animateTo(gp);
         
     Log.e("String is:", sb.toString());
     showDialog(sb.toString());      
  }           
      
  List providers=locationmngr.getProviders(true);
      
  for(String provider:providers)
  {
   locationmngr.requestLocationUpdates(provider,1000, 0,new LocationListener() 
   {    
    public void onStatusChanged(String provider, int status, Bundle extras) {
     // TODO Auto-generated method stub     
    }    
    public void onProviderEnabled(String provider) {
     // TODO Auto-generated method stub     
    }    
    public void onProviderDisabled(String provider) {
     // TODO Auto-generated method stub     
    }    
    public void onLocationChanged(Location location) {
     // TODO Auto-generated method stub     
    }
   });
   sb.append("\n").append(provider).append(":");
   Location loc=locationmngr.getLastKnownLocation(provider);
   
   if(loc!=null)
   {
    double lat=loc.getLatitude();
    double lon=loc.getLongitude();
    sb.append(lat).append(",").append(lon);        
   }
   else
   {
    sb.append("No Location found");
   }
  } 
 }
   public String[] Split(String splitStr, String delimiter)
     {
             StringBuffer token = new StringBuffer();
             Vector tokens = new Vector();
             // split
             char[] chars = splitStr.toCharArray();
             for (int i=0; i < chars.length; i++)
             {
                 if (delimiter.indexOf(chars[i]) != -1)
                 {
                     // we bumbed into a delimiter
                     if (token.length() > 0)
                     {
                         tokens.addElement(token.toString());
                         token.setLength(0);
                     }
                 }
                 else
                 {
                     token.append(chars[i]);
                 }
             }
             // don't forget the "tail"...
             if (token.length() > 0)
             {
                 tokens.addElement(token.toString());
             }
             // convert the vector into an array
             String[] splitArray = new String[tokens.size()];
             for (int i=0; i < splitArray.length; i++)
             {
                 splitArray[i] = (String)tokens.elementAt(i);
             }
             return splitArray;
     }
   
  public void showDialog(String msg)
  {      
        AlertDialog.Builder alt_bld = new AlertDialog.Builder(this);
      alt_bld.setMessage(msg)
      .setCancelable(false)
      .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
      public void onClick(DialogInterface dialog, int id) {
      // Action for 'Yes' Button
      }
      })
      .setNegativeButton("No", new DialogInterface.OnClickListener() {
      public void onClick(DialogInterface dialog, int id) {
      //  Action for 'NO' Button
      dialog.cancel();
      }
      });
      AlertDialog alert = alt_bld.create();
      // Title for AlertDialog
      alert.setTitle("Massege");
      // Icon for AlertDialog
      
      alert.show();
         // Perform action on click      
  }      
}
Download complete source code click here.