Locating user input address in Google Maps Android api v2 with Geocoding api

July 3, 2013
By

Geocoding is the process of converting a location address into geographic coordinates ( latitude and longitude).

This Android application facilitates users to input a location address, then the application can find the a set  of geographic coordinates that matches user input address and marks the corresponding locations in Google Maps Android API V2.



In order to find the geographic coordinates corresponding to user input address, this application uses Google’s Geocoding API (V3).

This application is an alternative to the application that we have developed in the article titled Android Geocoding – Showing User Input Location on Google Map Android API V2 where Geocoding is done using Android’s Geocoder class. Since Android’s Geocoder is not the part of standard Android open source project, Google’s Geocoding api is highly recommended for geocoding processes in Android applications.

This application is developed in Eclipse (4.2.1) with ADT plugin (22.0.1) and Android SDK (22.0.1) and tested in real devices with Android versions 2.3.6  ( GingerBread ) and 4.1.2 ( Jelly Bean ).



1. Create a new Android application project with the given below details

Application Name : LocationGeocodingAPIV2

Project Name : LocationGeocodingAPIV2

Package Name : in.wptrafficanalyzer.locationgeocodingapiv2

Minimum Required SDK : API 8: Android 2.2 ( Froyo )

Target SDK : API 17: Android 4.2 ( Jelly Bean )

Compile With: API 17: Android 4.2 ( Jelly Bean )

Theme : Holo Light with Dark Action Bar


2. 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


3. Referencing the Google Play Services library in this project

Please follow the given below link to reference the Google Play Service library into this project

http://developer.android.com/tools/projects/projects-eclipse.html#ReferencingLibraryProject


4. 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


5. 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 menu, Click “Android Tools -> Add Support Library “

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


<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">LocationGeocodingAPIV2</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>
    <string name="find">Find</string>
    <string name="hint">Enter Place</string>
</resources>


7. 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" >

    <Button
        android:id="@+id/btn_show"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/find"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true" />

    <EditText
        android:id="@+id/et_place"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="@string/hint"
        android:inputType="text"
        android:layout_toLeftOf="@id/btn_show" />

    <fragment
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/et_place"
        class="com.google.android.gms.maps.SupportMapFragment" />

</RelativeLayout>


8. Create a new class namely “GeocodeJSONParser” in the file src/in/wptrafficanalyzer/locationgeocodingapiv2/GeocodeJSONParser.java


package in.wptrafficanalyzer.locationgeocodingapiv2;

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

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class GeocodeJSONParser {

    /** Receives a JSONObject and returns a list */
    public List<HashMap<String,String>> parse(JSONObject jObject){

        JSONArray jPlaces = null;
        try {
            /** Retrieves all the elements in the 'places' array */
            jPlaces = jObject.getJSONArray("results");
        } catch (JSONException e) {
            e.printStackTrace();
        }
        /** Invoking getPlaces with the array of json object
        * where each json object represent a place
        */
        return getPlaces(jPlaces);
    }

    private List<HashMap<String, String>> getPlaces(JSONArray jPlaces){
        int placesCount = jPlaces.length();
        List<HashMap<String, String>> placesList = new ArrayList<HashMap<String,String>>();
        HashMap<String, String> place = null;

        /** Taking each place, parses and adds to list object */
        for(int i=0; i<placesCount;i++){
            try {
                /** Call getPlace with place JSON object to parse the place */
                place = getPlace((JSONObject)jPlaces.get(i));
                placesList.add(place);

            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        return placesList;
    }

    /** Parsing the Place JSON object */
    private HashMap<String, String> getPlace(JSONObject jPlace){

        HashMap<String, String> place = new HashMap<String, String>();
        String formatted_address = "-NA-";
        String lat="";
        String lng="";

        try {
            // Extracting formatted address, if available
            if(!jPlace.isNull("formatted_address")){
                formatted_address = jPlace.getString("formatted_address");
            }

            lat = jPlace.getJSONObject("geometry").getJSONObject("location").getString("lat");
            lng = jPlace.getJSONObject("geometry").getJSONObject("location").getString("lng");

            place.put("formatted_address", formatted_address);
            place.put("lat", lat);
            place.put("lng", lng);

        }catch (JSONException e) {
            e.printStackTrace();
        }
        return place;
    }
}


9. Update the class “MainActivity” in the file src/in/wptrafficanalyzer/locationgeocodingapiv2/MainActivity.java


package in.wptrafficanalyzer.locationgeocodingapiv2;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;

import org.json.JSONObject;

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
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 {

    Button mBtnFind;
    GoogleMap mMap;
    EditText etPlace;

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

        // Getting reference to the find button
        mBtnFind = (Button) findViewById(R.id.btn_show);

        // Getting reference to the SupportMapFragment
        SupportMapFragment mapFragment = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map);

        // Getting reference to the Google Map
        mMap = mapFragment.getMap();

        // Getting reference to EditText
        etPlace = (EditText) findViewById(R.id.et_place);

        // Setting click event listener for the find button
        mBtnFind.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // Getting the place entered
                String location = etPlace.getText().toString();

                if(location==null || location.equals("")){
                    Toast.makeText(getBaseContext(), "No Place is entered", Toast.LENGTH_SHORT).show();
                    return;
                }

                String url = "https://maps.googleapis.com/maps/api/geocode/json?";

                try {
                    // encoding special characters like space in the user input place
                    location = URLEncoder.encode(location, "utf-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }

                String address = "address=" + location;

                String sensor = "sensor=false";

                // url , from where the geocoding data is fetched
                url = url + address + "&" + sensor;

                // Instantiating DownloadTask to get places from Google Geocoding service
                // in a non-ui thread
                DownloadTask downloadTask = new DownloadTask();

                // Start downloading the geocoding places
                downloadTask.execute(url);
            }
        });
    }

    private String downloadUrl(String strUrl) throws IOException{
        String data = "";
        InputStream iStream = null;
        HttpURLConnection urlConnection = null;
        try{
            URL url = new URL(strUrl);
            // Creating an http connection to communicate with url
            urlConnection = (HttpURLConnection) url.openConnection();

            // Connecting to url
            urlConnection.connect();

            // Reading data from url
            iStream = urlConnection.getInputStream();

            BufferedReader br = new BufferedReader(new InputStreamReader(iStream));

            StringBuffer sb = new StringBuffer();

            String line = "";
            while( ( line = br.readLine()) != null){
                sb.append(line);
            }

            data = sb.toString();
            br.close();

        }catch(Exception e){
            Log.d("Exception while downloading url", e.toString());
        }finally{
            iStream.close();
            urlConnection.disconnect();
        }

        return data;
    }
    /** A class, to download Places from Geocoding webservice */
    private class DownloadTask extends AsyncTask<String, Integer, String>{

        String data = null;

        // Invoked by execute() method of this object
        @Override
        protected String doInBackground(String... url) {
            try{
                data = downloadUrl(url[0]);
            }catch(Exception e){
                Log.d("Background Task",e.toString());
            }
            return data;
        }

        // Executed after the complete execution of doInBackground() method
        @Override
        protected void onPostExecute(String result){

            // Instantiating ParserTask which parses the json data from Geocoding webservice
            // in a non-ui thread
            ParserTask parserTask = new ParserTask();

            // Start parsing the places in JSON format
            // Invokes the "doInBackground()" method of the class ParseTask
            parserTask.execute(result);
        }
    }

    /** A class to parse the Geocoding Places in non-ui thread */
    class ParserTask extends AsyncTask<String, Integer, List<HashMap<String,String>>>{

        JSONObject jObject;

        // Invoked by execute() method of this object
        @Override
        protected List<HashMap<String,String>> doInBackground(String... jsonData) {

            List<HashMap<String, String>> places = null;
            GeocodeJSONParser parser = new GeocodeJSONParser();

            try{
                jObject = new JSONObject(jsonData[0]);

                /** Getting the parsed data as a an ArrayList */
                places = parser.parse(jObject);

            }catch(Exception e){
                Log.d("Exception",e.toString());
            }
            return places;
        }

        // Executed after the complete execution of doInBackground() method
        @Override
        protected void onPostExecute(List<HashMap<String,String>> list){

            // Clears all the existing markers
            mMap.clear();

            for(int i=0;i<list.size();i++){

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

                // Getting a place from the places list
                HashMap<String, String> hmPlace = list.get(i);

                // Getting latitude of the place
                double lat = Double.parseDouble(hmPlace.get("lat"));

                // Getting longitude of the place
                double lng = Double.parseDouble(hmPlace.get("lng"));

                // Getting name
                String name = hmPlace.get("formatted_address");

                LatLng latLng = new LatLng(lat, lng);

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

                // Setting the title for the marker
                markerOptions.title(name);

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

                // Locate the first location
                if(i==0)
                    mMap.animateCamera(CameraUpdateFactory.newLatLng(latLng));
            }
        }
    }

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


10. Update the file AndroidManifest.xml


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

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

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

    <uses-permission android:name="in.wptrafficanalyzer.locationgeocodingapiv2.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.locationgeocodingapiv2.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_ANDROID_API_KEY"/>

    </application>
</manifest>


11. Screenshots of the application

Inputting address

Figure 1 : Inputting address

Showing user input location in Google Maps Android API V2

Figure 2 : Showing user input location in Google Maps Android API V2


12 Download the 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: , , , , ,

21 Responses to Locating user input address in Google Maps Android api v2 with Geocoding api

  1. tawisak on July 8, 2013 at 1:57 pm

    If after search, How can display kml file that store in assets.

    Thank you in advance

    • george on July 8, 2013 at 4:44 pm

      Hi Tawisak,
      We can display the contents of KML data by parsing it manually.

      • tawisak on July 9, 2013 at 7:21 am

        Can you sample code for it?.

        in tutorial..

        Thank you inadvance.

  2. Andre on July 11, 2013 at 7:31 pm

    How do I plot a route from my location to the location indicated by the EditText ?

  3. Jacks on July 22, 2013 at 4:02 pm

    Pls would you mind to explain this code?

    String url = “https://maps.googleapis.com/maps/api/geocode/json?”

    Thanks

    • george on July 22, 2013 at 5:54 pm

      Please refer this documentation.

      • Jacks on July 22, 2013 at 6:47 pm

        thanks

        but my question is how to make my position(GPS positon) using that JSON parameter?
        ex.
        http://maps.googleapis.com/maps/api/directions/json?origin=(MY CURRENT LOCATION using gps positon)&destination=Montreal&sensor=true?

        is that true or? im still blur about using that parameter.

        thanks

        • george on July 22, 2013 at 7:27 pm

          Hi Jacks,
          I think, you are suffering to get latitude and longitude of current location. If so, please follow this article.

  4. dat steven on July 28, 2013 at 8:29 am

    Thanks sir for this tutorial. It’s very clear. Can you build a example android google map apiv2 app using webservice (lat/long stored in webservice).
    Thanks for all!

    • george on July 28, 2013 at 11:00 am

      Hi Steven,
      Thanks for the suggestion. It is added to the pipeline.

  5. vib on December 10, 2013 at 5:09 pm

    If run on my mobile device not run and show error “unfortumately googlelocation has stopped”

    • amit sharma on February 13, 2014 at 5:28 pm

      Hi,
      Great Code ….thanks George Mathew

  6. Rajneesh on February 27, 2014 at 10:47 pm

    Great tutorial, it’s lots of help me. Great Work… Thank you thank you so much…

  7. soyeon on April 16, 2014 at 3:36 am

    what’s the version of geocoding? v2 or v3?

  8. Perez on December 1, 2014 at 7:41 pm

    How i can get the location from webservice and show it in google map?

  9. Athira on December 13, 2014 at 12:37 pm

    I updated the manifest file with my api key but while launching the app it crashes. No errors are shown in project. I have referenced the google play services library project also. My device has play services installed on it. other android apps which use play services and maps are running fine but this app crashes everytime I try to run it. Please help.

  10. Kheng on February 16, 2015 at 10:03 pm

    Thanks George for the wonderful tutorial. I’m struggling to get the short_name in the Geocode return value. Do you have an example for that?

  11. Mounika on February 18, 2015 at 10:39 am

    Hi,Great code it helped me a lot,but how to get lat long values of the address provided in the edittext

  12. Hardik parmar on May 8, 2015 at 5:56 pm

    Hi , its good job, and its nice easy to set marker in search point.

  13. Giba on October 20, 2015 at 11:03 pm

    Really Appreciate your great tutorial

  14. Vishal on January 8, 2016 at 2:21 pm

    hello sir,

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

    above all the import package generate error..
    and error is:

    The import com.google.android.gms.maps cannot be resolved

    how i can solve?

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