Android Reverse Geocoding using Geocoder at touched location in Google Map

October 2, 2012
By

Reverse geocoding is the process of transforming a (latitude, longitude) coordinate into a (partial) address.

In this article, we will create an Android application which adds a marker on the touched location of the Google Map. It also displays the address of the touched location in a TextView using reverse Geocoding.

For reverse Geocoding, this application make use Android’s Geocoder API.

This application is developed in Eclipse ( 4.2.0 ) with ADT plugin (20.0.3 ) and Android SDK ( R20.0.3 ).

Update : An upgraded version of this application ( using Google Map Android API V2 ) is available in the article titled “Android Reverse Geocoding at touched location in Google Map Android API V2


1. Create a new Android application project namely “LocationReverseGeocoding”

New Android Application Project

Figure 1 : New Android Application Project


2. Design application launcher icon for this application

Design Application Launcher Icon

Figure 2 : Design Application Launcher Icon


3. Create a blank activity to define the class MainActivity

Create a blank activity

Figure 3 : Create a blank activity


4. Enter MainActivity details

Enter MainActivity Details

Figure 4 : Enter MainActivity Details


5. Delete Android’s Support Library from this project

By default Eclipse ( 4.2.0) adds Android Support Library to  Android application project. For this application, we don’t need to use this support library. So the library file libs/android-support-v4.jar may be removed manually via ProjectExplorer by simply right click on the file and then clicking the menu item “delete”.


6. Obtain Google Map Key

Google’s Map Key for the Android application will be available here.

The map key obtained has to be entered as the value of the attribute android:apiKey in the layout file res/layout/activity_main.


7. Create a new folder namely drawable under the folder “res”


8. Download the given below image file namely “marker.png” to the folder “res/drawable”


9. Update the file res/values/strings.xml


<resources>
    <string name="app_name">LocationReverseGeocoding</string>
    <string name="hello_world">Hello world!</string>
    <string name="menu_settings">Settings</string>
    <string name="title_activity_main">ReverseGeocoding</string>
</resources>


10. Update the file res/layout/activity_main.xml


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/tv_location"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        tools:context=".MainActivity" />

    <com.google.android.maps.MapView
        android:id="@+id/map_view"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:apiKey="0u7AJChI1NV8vCpj21C0Cq8YnNMrB6YMgigu0GA"
        android:clickable="true"
        android:layout_below="@id/tv_location" />
</RelativeLayout>

Note : Replace the value of android:apiKey (Line 17)  with the Google Map Key obtained in Step 6


11. Create a class namely TouchedLocationOverlay in the file src/in/wptrafficanalyzer/locationreversegeocoding/TouchedLocationOverlay.java


package in.wptrafficanalyzer.locationreversegeocoding;

import java.util.ArrayList;
import java.util.List;

import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

public class TouchedLocationOverlay extends ItemizedOverlay<OverlayItem> {

    private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
    private Handler handler;

    public TouchedLocationOverlay(Drawable defaultMarker,Handler h) {
        super(boundCenterBottom(defaultMarker));

        // Handler object instantiated in the class MainActivity
        this.handler = h;
    }

    // Executed, when populate() method is called
    @Override
    protected OverlayItem createItem(int arg0) {
        return mOverlays.get(arg0);
    }

    @Override
    public int size() {
        return mOverlays.size();
    }

    public void addOverlay(OverlayItem overlay){
        mOverlays.add(overlay);
        populate(); // Invokes the method createItem()
    }

    // This method is invoked, when user tap on the map
    @Override
    public boolean onTap(GeoPoint p, MapView map) {

        List<Overlay> overlays = map.getOverlays();

        // Creating a Message object to send to Handler
        Message message = new Message();

        // Creating a Bundle object ot set in Message object
        Bundle data = new Bundle();

        // Setting latitude in Bundle object
        data.putInt("latitude", p.getLatitudeE6());

        // Setting longitude in the Bundle object
        data.putInt("longitude", p.getLongitudeE6());

        // Setting the Bundle object in the Message object
        message.setData(data);

        // Sending Message object to handler
        handler.sendMessage(message);

        return super.onTap(p, map);
    }
}


12. Update the class MainActivity in the file src/in/wptrafficanalyzer/locationreversegeocoding/MainActivity.java


package in.wptrafficanalyzer.locationreversegeocoding;

import java.io.IOException;
import java.util.List;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.location.Address;
import android.location.Geocoder;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.widget.TextView;

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 com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

public class MainActivity extends MapActivity {

    private MapView mapView;
    private TextView tvLocation;

    // Handles Taps on the Google Map
    Handler h = new Handler(){

        // Invoked by the method onTap()
        // in the class CurrentLocationOverlay
        @Override
        public void handleMessage(Message msg) {
            Bundle data = msg.getData();

            // Getting the Latitude of the location
            int latitude = data.getInt("latitude");

            // Getting the Longitude of the location
            int longitude = data.getInt("longitude");

            // Show the location in the Google Map
            showLocation(latitude,longitude);
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Getting reference to map_view available in activity_main.xml
        mapView = (MapView) findViewById(R.id.map_view);

        // Getting reference to tv_location available in activity_main.xml
        tvLocation = (TextView) findViewById(R.id.tv_location);

        // Default Latitude
        int latitude = 28426365;

        // Default Longitude
        int longitude = 77320393;

        // Show the location in the Google Map
        showLocation(latitude,longitude);
    }

    private void showLocation(int latitude, int longitude){

        // Setting Zoom Controls
        mapView.setBuiltInZoomControls(true);

        // Getting the MapController
        MapController mapController = mapView.getController();

        // Getting Overlays of the map
        List<Overlay> overlays = mapView.getOverlays();

        // Getting Drawable object corresponding to a resource image
        Drawable drawable = getResources().getDrawable(R.drawable.marker);

        // Creating an ItemizedOverlay
        TouchedLocationOverlay locationOverlay = new TouchedLocationOverlay(drawable,h);

        // Getting the MapController
        MapController mc = mapView.getController();

        // Creating an instance of GeoPoint, to display in Google Map
        GeoPoint p = new GeoPoint(
                        latitude,
                        longitude
                    );

        // Locating the point in the Google Map
        mc.animateTo(p);

        // Creating an OverlayItem to mark the point
        OverlayItem overlayItem = new OverlayItem(p, "Item", "Item");

        // Adding the OverlayItem in the LocationOverlay
        locationOverlay.addOverlay(overlayItem);

        // Clearing the overlays
        overlays.clear();

        // Adding locationOverlay to the overlay
        overlays.add(locationOverlay);

        // Redraws the map
        mapView.invalidate();

        Double[] lat_long = new Double[] { latitude/1E6, longitude/1E6 };

        // Executing ReverseGeocodingTask to get Address
        new ReverseGeocodingTask(getBaseContext()).execute(lat_long);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return false;
    }

    @Override
    protected boolean isRouteDisplayed() {
        // TODO Auto-generated method stub
        return false;
    }

    private class ReverseGeocodingTask extends AsyncTask<Double, Void, String>{
        Context mContext;

        public ReverseGeocodingTask(Context context){
            super();
            mContext = context;
        }

        @Override
        protected String doInBackground(Double... params) {
            Geocoder geocoder = new Geocoder(mContext);
            double latitude = params[0].doubleValue();
            double longitude = params[1].doubleValue();

            List<Address> addresses = null;
            String addressText="";

            try {
                addresses = geocoder.getFromLocation(latitude, longitude,1);
            } catch (IOException e) {
                e.printStackTrace();
            }

            if(addresses != null && addresses.size() > 0 ){
                Address address = addresses.get(0);

                addressText = String.format("%s, %s, %s",
                        address.getMaxAddressLineIndex() > 0 ? address.getAddressLine(0) : "",
                        address.getLocality(),
                        address.getCountryName());
            }

            return addressText;
        }

        @Override
        protected void onPostExecute(String addressText) {
            // Setting address of the touched Position
            tvLocation.setText(addressText);
        }
    }
}


13. Update the file AndroidManifest.xml


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="in.wptrafficanalyzer.locationreversegeocoding"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="4"
        android:targetSdkVersion="15" />

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <uses-library android:name="com.google.android.maps"/>

        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>


14. Screenshot of the application

Showing address of the touched location by Reverse Geocoding

Figure 5 : Showing address of the touched location by Reverse Geocoding in Google APIs Emulator ( API Level 4 )


15. Download


16. Reference

http://developer.android.com/guide/index.html


How to hire me?

I am George Mathew, working as software architect and Android app developer at wptrafficanalyzer.in

You can hire me on hourly basis or on project basis for Android applications development.

For hiring me, please mail your requirements to info@wptrafficanalyzer.in.

My other blogs
store4js.blogspot.com


Android Knowledge Quiz

Ready to test your knowledge in Android? Take this quiz :



Tags: , , , , , , , ,

4 Responses to Android Reverse Geocoding using Geocoder at touched location in Google Map

  1. GauravKumawat on December 26, 2012 at 12:14 pm

    Superb …………………george..

  2. Arunanchal on January 2, 2013 at 9:22 pm

    Thanks a lot for program,
    how can be displayed name of state inside that area for the address.?

  3. swapnil on October 22, 2013 at 11:51 am

    I appreciate your work,Very much thanks to made such a program

  4. swapnil on October 23, 2013 at 12:03 pm

    java.io.ioexception:unable to parse repsonse from server

    Plz give me soltion as soon as possible

Leave a Reply

Your email address will not be published. Required fields are marked *

Be friend at g+

Subscribe for Lastest Updates

FBFPowered by ®Google Feedburner