Reverse Geocoding in Android Studio

Introduction

 
In this article, you will learn Reverse Geocoding using the XML request format. Reverse Geocoding is the process of getting the address of a location whose latitude and longitude are given by the user. The request from the user can be in XML format or in JSON format.
 
The reverse geocoding request format used in this article is of the format:
 
Note that for giving the latitude and longitude, the format should be: latitude, longitude. No space should be present between the two values.
 
Step 1
 
First, let us make a search layout where the user will enter the latitude and longitude value of the required location. Right-click on layout then select "New" -> "Layout Resource file". Name this file as "search_layout" and add the following code to it:
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.               android:orientation="vertical"  
  3.               android:layout_width="match_parent"  
  4.               android:layout_height="match_parent"  
  5.               android:background="#ffdbac">  
  6.   <EditText  
  7.           android:id="@+id/enter"  
  8.           android:layout_width="fill_parent"  
  9.           android:layout_height="wrap_content"  
  10.           android:textSize="20dp"  
  11.           android:hint="Enter the required Location...."  
  12.           android:layout_marginTop="40dp"  
  13.           android:layout_marginLeft="20dp"  
  14.           android:layout_marginRight="20dp"/>  
  15.   <Button  
  16.           android:id="@+id/search"  
  17.           android:layout_width="wrap_content"  
  18.           android:layout_height="wrap_content"  
  19.           android:layout_marginLeft="130dp"  
  20.           android:layout_marginTop="40dp"  
  21.           android:text="Search"  
  22.           android:background="@drawable/button_lay"  
  23.           android:paddingRight="10dp"  
  24.           android:paddingLeft="10dp"  
  25.             />  
  26. </LinearLayout> 
The layout looks like:
 
im1.jpg
 
Step 2
 
Open the "activity_main" layout file and add the following code to it: (Inside LinearLayout element)
  1. <ListView  
  2.             android:id="@android:id/list"  
  3.             android:layout_width="fill_parent"  
  4.             android:layout_height="wrap_content"/> 
Step 3
 
Create one more layout file. Name it "list_item" and add the following code to it (inside the LinearLayout element):
  1. <TextView  
  2.            android:id="@+id/address"  
  3.            android:layout_width="fill_parent"  
  4.            android:layout_height="wrap_content"  
  5.            android:textSize="16sp"  
  6.            android:textStyle="bold"  
  7.            android:paddingTop="6dip"  
  8.            android:paddingBottom="2dip" />  
Step 4
 
Right-click on your package name then select "New" -> "Java class". Name this Java class as "Search" and add the following code to it:
  1. package com.chhavi.reversegeocoding;  
  2.    
  3. import android.app.Activity;  
  4. import android.content.Context;  
  5. import android.content.Intent;  
  6. import android.os.Bundle;  
  7. import android.view.View;  
  8. import android.widget.Button;  
  9. import android.widget.EditText;  
  10.    
  11. public class Search extends Activity {  
  12.     EditText enter;  
  13.     Button b;  
  14.     String place;  
  15.     final Context context=this;  
  16.     @Override  
  17.     protected void onCreate(Bundle savedInstanceState) {  
  18.         super.onCreate(savedInstanceState);  
  19.         setContentView(R.layout.search_layout);  
  20.         enter=(EditText)findViewById(R.id.enter);  
  21.         b=(Button)findViewById(R.id.search);  
  22.         b.setOnClickListener(new View.OnClickListener() {  
  23.             @Override  
  24.             public void onClick(View v) {  
  25.                 Intent i=new Intent(context,MainActivity.class);  
  26.                 place=enter.getText().toString();  
  27.                 i.putExtra("place",place);  
  28.                 startActivity(i);   
  29.             }  
  30.         });  
  31.     }  
Step 5
 
Create another class and name it "XmlParsing". Write the following code in it:
  1. package com.chhavi.reversegeocoding;  
  2.    
  3. import android.util.Log;   
  4. import org.apache.http.HttpEntity;  
  5. import org.apache.http.HttpResponse;  
  6. import org.apache.http.client.ClientProtocolException;  
  7. import org.apache.http.client.entity.UrlEncodedFormEntity;  
  8. import org.apache.http.client.methods.HttpGet;  
  9. import org.apache.http.client.methods.HttpPost;  
  10. import org.apache.http.impl.client.DefaultHttpClient;  
  11. import org.apache.http.util.EntityUtils;  
  12. import org.w3c.dom.Document;  
  13. import org.w3c.dom.Element;  
  14. import org.w3c.dom.Node;  
  15. import org.w3c.dom.NodeList;  
  16. import org.xml.sax.InputSource;  
  17. import org.xml.sax.SAXException;   
  18. import java.io.IOException;  
  19. import java.io.StringReader;  
  20. import java.io.UnsupportedEncodingException;   
  21. import javax.xml.parsers.DocumentBuilder;  
  22. import javax.xml.parsers.DocumentBuilderFactory;  
  23. import javax.xml.parsers.ParserConfigurationException;  
  24.    
  25. public class XmlParsing {  
  26.    
  27.     public XmlParsing() {  
  28.    
  29.     }  
  30.    
  31.     public String getXmlFromUrl(String url) {  
  32.         String xml = null;  
  33.    
  34.         try {  
  35.    
  36.             DefaultHttpClient httpClient = new DefaultHttpClient();  
  37.             HttpPost httpPost = new HttpPost(url);       
  38.             Log.i("URL.......",url);  
  39.             HttpResponse httpResponse = httpClient.execute(httpPost);  
  40.    
  41.             HttpEntity httpEntity = httpResponse.getEntity();  
  42.    
  43.             xml = EntityUtils.toString(httpEntity);  
  44.    
  45.         } catch (UnsupportedEncodingException e) {  
  46.             e.printStackTrace();  
  47.         } catch (ClientProtocolException e) {  
  48.             e.printStackTrace();  
  49.         } catch (IOException e) {  
  50.             e.printStackTrace();  
  51.         }  
  52.    
  53.         return xml;  
  54.     }  
  55.     
  56.     public Document getDomElement(String xml){  
  57.         Document doc = null;  
  58.         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();  
  59.         try {  
  60.             DocumentBuilder db = dbf.newDocumentBuilder();  
  61.             InputSource is = new InputSource();  
  62.             is.setCharacterStream(new StringReader(xml));  
  63.             doc = db.parse(is);  
  64.    
  65.         } catch (ParserConfigurationException e) {  
  66.             Log.e("Error: ", e.getMessage());  
  67.             return null;  
  68.         } catch (SAXException e) {  
  69.             Log.e("Error: ", e.getMessage());  
  70.             return null;  
  71.         } catch (IOException e) {  
  72.             Log.e("Error: ", e.getMessage());  
  73.             return null;  
  74.         }  
  75.         return doc;  
  76.     }  
  77.    
  78.     public final String getElementValue( Node elem ) {  
  79.         Node child;  
  80.         if( elem != null){  
  81.             if (elem.hasChildNodes()){  
  82.                 for( child = elem.getFirstChild(); child != null; child = child.getNextSibling() ){  
  83.                     if( child.getNodeType() == Node.TEXT_NODE  ){  
  84.                         return child.getNodeValue();  
  85.                     }  
  86.                 }  
  87.             }  
  88.         }  
  89.         return "";  
  90.     }  
  91.    
  92.     public String getValue(Element item, String str) {  
  93.         NodeList n = item.getElementsByTagName(str);  
  94.         return this.getElementValue(n.item(0));  
  95.     }  
HttpEntity can send or receive HTTP messages. Entities can be found in a request or a response.
 
Document is the root of a document tree.
 
DocumentBuilderFactory defines a factory API that enables applications to obtain a parser that produces DOM object trees from XML documents.
 
DocumentBuilder takes XML as input and gives a DOM document object as output.
 
Step 6
 
Open "MainActivity" and add the following code to it:
  1. package com.chhavi.reversegeocoding;  
  2.    
  3. import android.app.ListActivity;  
  4. import android.app.ProgressDialog;  
  5. import android.content.Context;  
  6. import android.content.Intent;  
  7. import android.os.AsyncTask;  
  8. import android.os.Bundle;  
  9. import android.app.Activity;  
  10. import android.util.Log;  
  11. import android.view.Menu;  
  12. import android.widget.ListAdapter;  
  13. import android.widget.ListView;  
  14. import android.widget.SimpleAdapter;  
  15. import org.w3c.dom.Document;  
  16. import org.w3c.dom.Element;  
  17. import org.w3c.dom.NodeList;  
  18. import java.util.ArrayList;  
  19. import java.util.HashMap;  
  20.    
  21. public class MainActivity extends ListActivity {  
  22.    
  23.     private static String url = "http://maps.googleapis.com/maps/api/geocode/xml?latlng=";  
  24.      
  25.     static final String KEY_RESULT = "result"// parent node  
  26.     static final String KEY_FORMATTED_ADDRESS = "formatted_address";  
  27.     ArrayList<HashMap<String, String>> address_list = new ArrayList<HashMap<String, String>>();  
  28.     ListView listView ;  
  29.    
  30.     @Override  
  31.     protected void onCreate(Bundle savedInstanceState) {  
  32.         super.onCreate(savedInstanceState);  
  33.         setContentView(R.layout.activity_main);  
  34.    
  35.         Intent intent = getIntent();  
  36.         String enter= intent.getStringExtra("place");  
  37.         Log.i("place..",enter+"");  
  38.         url=url+enter+"&sensor=false";  
  39.         new Progress(MainActivity.this).execute();  
  40.         }  
  41.     private class Progress extends AsyncTask<String, Void, Boolean> {  
  42.         private ProgressDialog dialog;  
  43.    
  44.         public Progress(ListActivity activity) {  
  45.    
  46.             Log.i("constructor....""Called");  
  47.             context = activity;  
  48.             dialog = new ProgressDialog(context);  
  49.         }  
  50.    
  51.         private Context context;  
  52.    
  53.         protected void onPreExecute() {  
  54.             this.dialog.setMessage("Getting location....");  
  55.             this.dialog.show();  
  56.         }  
  57.    
  58.         @Override  
  59.         protected void onPostExecute(final Boolean success) {  
  60.             if (dialog.isShowing()) {  
  61.                 dialog.dismiss();  
  62.             }  
  63.             ListAdapter adapter = new SimpleAdapter(context, address_list, R.layout.list_item, new String[] { KEY_FORMATTED_ADDRESS }, new int[] { R.id.address });  
  64.             setListAdapter(adapter);  
  65.             listView = getListView();  
  66.         }  
  67.         protected Boolean doInBackground(final String... args) {  
  68.    
  69.             XmlParsing parser = new XmlParsing();  
  70.             String xml = parser.getXmlFromUrl(url);  
  71.             Document doc = parser.getDomElement(xml);  
  72.    
  73.             NodeList nl = doc.getElementsByTagName(KEY_RESULT);  
  74.    
  75.             for (int i = 0; i < nl.getLength(); i++) {  
  76.    
  77.                 HashMap<String, String> map = new HashMap<String, String>();  
  78.                 Element e = (Element) nl.item(i);  
  79.                 map.put(KEY_FORMATTED_ADDRESS, parser.getValue(e, KEY_FORMATTED_ADDRESS));  
  80.                 address_list.add(map);  
  81.             }  
  82.    
  83.             return null;  
  84.     }  
  85.     }  
  86.    
  87.     @Override  
  88.     public boolean onCreateOptionsMenu(Menu menu) {  
  89.         // Inflate the menu; this adds items to the action bar if it is present.  
  90.         getMenuInflater().inflate(R.menu.main, menu);  
  91.         return true;  
  92.     }     
I wanted to reach the "formatted_address" tag in the XML file. For reaching "formatted_address", the following parsing is required inside the "GeocodeResponse" tag of the XML file: results->formatted_address.
 
Step 7
 
Make the following changes in "AndroidManifest":
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.chhavi.reversegeocoding"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.    
  7.   <uses-permission android:name="android.permission.INTERNET" />  
  8.    
  9.   <uses-sdk  
  10.       android:minSdkVersion="7"  
  11.       android:targetSdkVersion="16" />  
  12.    
  13.   <application  
  14.       android:allowBackup="true"  
  15.       android:icon="@drawable/ic_launcher"  
  16.       android:label="@string/app_name"  
  17.       android:theme="@style/AppTheme" >  
  18.     <activity  
  19.         android:name="com.chhavi.reversegeocoding.Search"  
  20.         android:label="@string/app_name" >  
  21.       <intent-filter>  
  22.         <action android:name="android.intent.action.MAIN" />  
  23.         <category android:name="android.intent.category.LAUNCHER" />  
  24.       </intent-filter>  
  25.     </activity>  
  26.    
  27.     <activity android:name=".MainActivity"  
  28.               android:label="Reverse Geocoding"/>  
  29.   </application>  
  30. </manifest> 
Output snapshots:
 
im2.jpg
 
On entering the latitude and longitude value (enter the latitude and longitude values without any space in between):
 
im3.jpg
 
On clicking the search button:
 
im4.jpg
 
im5.jpg
 
 
Thank you... Enjoy coding :)


Similar Articles