Android Reverse Geocoding at touched location in Google Map Android API V2

January 9, 2013
By

In this article we will create an Android application which resolves (partial) address from the latitude and longitude of the touched position of the Google Map Android API V2.

The process of resolving location address from latitude and longitude is called reverse Geocoding and for this we will make use Google’s Geocoder library API.

This application is developed in Eclipse 4.2.1 with ADT plugin ( 21.0.0 ) and Android SDK ( 21.0.0 ) and is tested in a real Android Phone with Android ( 2.3.6 ).

This application is an upgraded version of the application developed in the article titled “Android Reverse Geocoding using Geocoder at touched Location in Google Map“.


1. Download and configure Google Play Services Library in Eclipse

Please follow the given below link to setup Google Play Service library in Eclipse.

http://developer.android.com/google/play-services/setup.html


2. Create a new Android Application Project namely “LocationReverseGeocodingV2″

New Android Application Project

Figure 1 : New Android Application Project


3. Configure Android Application Project

Configure Application Project

Figure 2 : Configure Application Project


4. Design Application Launcher Icon

Design application launcher icon

Figure 3 : Design application launcher icon


5. Create a blank activity

Create a blank activity

Figure 4 : Create a blank activity


6. Enter Main Activity Details

Enter Main Activity Details

Figure 5 : Enter Main Activity Details


7. Link to Google Play Service Library

Link Google Play Services Library

Figure 6 : Link Google Play Services Library


8. Get the API key for Google Maps Android API v2

We need to get an API key from Google to use Google Maps in Android application. Please follow the given below link to get the API key for Google Maps Android API v2.

https://developers.google.com/maps/documentation/android/start


9. Add Android Support library to this project

By default, Android support library (android-support-v4.jar ) is added to this project by Eclipse IDE to the directory libs. If it is not added, we can do it manually by doing the following steps :

  • Open Project Explorer by Clicking “Window -> Show View -> Project Explorer”
  • Right click this project
  • Then from popup window, Click “Android Tools -> Add Support Library “

10. Update the file AndroidManfiest.xml


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="in.wptrafficanalyzer.locationreversegeocodingv2"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="16" />

    <permission
        android:name="in.wptrafficanalyzer.locationreversegeocodingv2.permission.MAPS_RECEIVE"
        android:protectionLevel="signature"/>

    <uses-permission android:name="in.wptrafficanalyzer.locationreversegeocodingv2.permission.MAPS_RECEIVE"/>

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

        <activity
            android:name="in.wptrafficanalyzer.locationreversegeocodingv2.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="YOUR_API_KEY"/>
    </application>
</manifest>

Note : In the above code, replace “YOUR_API_KEY” with the api key, you generated in step 8.


11. Update the layout 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"
    tools:context=".MainActivity" >

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        class="com.google.android.gms.maps.SupportMapFragment"/>

</RelativeLayout>


12. Update the file src/in/wptrafficanalyzer/locationreversegeocodingv2/MainActivity.java


package in.wptrafficanalyzer.locationreversegeocodingv2;

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

import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.Menu;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMapClickListener;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

public class MainActivity extends FragmentActivity {

    GoogleMap googleMap;
    MarkerOptions markerOptions;
    LatLng latLng;

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

        SupportMapFragment supportMapFragment = (SupportMapFragment)
                getSupportFragmentManager().findFragmentById(R.id.map);

        // Getting a reference to the map
        googleMap = supportMapFragment.getMap();

        // Setting a click event handler for the map
        googleMap.setOnMapClickListener(new OnMapClickListener() {

            @Override
            public void onMapClick(LatLng arg0) {

                // Getting the Latitude and Longitude of the touched location
                latLng = arg0;

                // Clears the previously touched position
                googleMap.clear();

                // Animating to the touched position
                googleMap.animateCamera(CameraUpdateFactory.newLatLng(latLng));

                // Creating a marker
                markerOptions = new MarkerOptions();

                // Setting the position for the marker
                markerOptions.position(latLng);

                // Placing a marker on the touched position
                googleMap.addMarker(markerOptions);

                // Adding Marker on the touched location with address
                new ReverseGeocodingTask(getBaseContext()).execute(latLng);

            }
        });
    }

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

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

        // Finding address using reverse geocoding
        @Override
        protected String doInBackground(LatLng... params) {
            Geocoder geocoder = new Geocoder(mContext);
            double latitude = params[0].latitude;
            double longitude = params[0].longitude;

            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 the title for the marker.
            // This will be displayed on taping the marker
            markerOptions.title(addressText);

            // Placing a marker on the touched position
            googleMap.addMarker(markerOptions);

        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}


13. Screenshot of the application in execution


Showing address of the touched position using Google's Geocoder API

Figure 7 : Showing address of the touched position using Google’s Geocoder API


14. Download Source Code


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: , , , , ,

11 Responses to Android Reverse Geocoding at touched location in Google Map Android API V2

  1. Kijoo Nguyen on March 9, 2013 at 9:07 pm

    This doesn’t work for me.
    The map works fine but the address return is blank

  2. swathi on March 16, 2013 at 1:52 pm

    This doesn’t work for me.
    The map works fine but the address return is null in the place name

  3. pratik on April 20, 2013 at 3:20 pm

    Thanx for your valuable post but there is 1 problem..can you please help me…i have done google search but couldn’t find any solution.

    java.io.IOException: Service not Available

    it throws exception on this line in your code
    addresses = geocoder.getFromLocation(latitude, longitude,1);

    any idea?

  4. Hoon Lee on May 9, 2013 at 11:21 am

    Thank you for this source. I take advantage of it a lot. Anyway I have tried this one, it works but address dialog doesn’t appear on the map. I really appreciate if you give me some hint for it.

  5. harishkumar on January 11, 2014 at 1:32 pm

    I am really sorry for last comment …and Thank you Its working for me …it takes some to fetch address ..Working fine

  6. suresh on March 21, 2014 at 1:25 pm

    can i add weather layer in mapversion v2 with my current location

  7. Manish Sindhal on August 29, 2014 at 3:26 pm

    It’s great work for me but some changes in show address in marker.

    Thanks

  8. Alicia Beltran on November 4, 2014 at 9:33 am

    Hi, somethink wrong is happening.

    11-03 22:47:17.524: E/AndroidRuntime(30376): FATAL EXCEPTION: AsyncTask #3
    11-03 22:47:17.524: E/AndroidRuntime(30376): Process: in.wptrafficanalyzer.locationwaypointmapv2, PID: 30376
    11-03 22:47:17.524: E/AndroidRuntime(30376): java.lang.RuntimeException: An error occured while executing doInBackground()
    11-03 22:47:17.524: E/AndroidRuntime(30376): at android.os.AsyncTask$3.done(AsyncTask.java:300)
    11-03 22:47:17.524: E/AndroidRuntime(30376): at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
    11-03 22:47:17.524: E/AndroidRuntime(30376): at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
    11-03 22:47:17.524: E/AndroidRuntime(30376): at java.util.concurrent.FutureTask.run(FutureTask.java:242)
    11-03 22:47:17.524: E/AndroidRuntime(30376): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
    11-03 22:47:17.524: E/AndroidRuntime(30376): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
    11-03 22:47:17.524: E/AndroidRuntime(30376): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
    11-03 22:47:17.524: E/AndroidRuntime(30376): at java.lang.Thread.run(Thread.java:841)
    11-03 22:47:17.524: E/AndroidRuntime(30376): Caused by: java.lang.NullPointerException
    11-03 22:47:17.524: E/AndroidRuntime(30376): at in.wptrafficanalyzer.locationwaypointmapv2.MainActivity$ReverseGeocodingTask.doInBackground(MainActivity.java:3150)
    11-03 22:47:17.524: E/AndroidRuntime(30376): at in.wptrafficanalyzer.locationwaypointmapv2.MainActivity$ReverseGeocodingTask.doInBackground(MainActivity.java:1)
    11-03 22:47:17.524: E/AndroidRuntime(30376): at android.os.AsyncTask$2.call(AsyncTask.java:288)
    11-03 22:47:17.524: E/AndroidRuntime(30376): at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    11-03 22:47:17.524: E/AndroidRuntime(30376): … 4 more

    I didnt identify what is happenning with those theat.

    Any suggestion?

  9. Abdul Khalik on June 9, 2015 at 5:01 pm

    Thans for your most valuable post. Google map is showing very well but address doesn’t return so plz help me how can I get address on map touch

  10. Abdul Khalik on June 16, 2015 at 11:47 am

    Solution: We will have to take a TextView in xml like that:

    and in MainActivity class initialize TextView and then set in post execute method like that:

    @Override
    protected void onPostExecute(String addressText) {
    // Setting address of the touched Position

    tvLocation.setText(addressText);
    }

    Your code will work 101% fine do enjoy this…

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