Android Geocoding – Showing User Input Location on Google Map

October 3, 2012
By

Geocoding is the process of transforming a street address or other description of a location into a (latitude, longitude) coordinate.

This application facilitates to find a location in the Google Map by entering location in a textview. On clicking the find button, the application contacts geocoding web service via Geocoder api with the user input location string. The list of addresses returned from the webservice will contain information such as latitude, longitude, address details etc. These information(latitude and longitude) will be used to plot the location in Google Map.

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

Update : An upgraded version of this application with Google Map Android API V2 is available in the article titled “Android Geocoding – Showing User Input Location on Google Map Android API V2“.


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

Create a new Android Application Project

Figure 1 : Create a new Android Application Project


2. Design application launcher icon

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">Geocoding Demo</string>
    <string name="hello_world">Hello world!</string>
    <string name="menu_settings">Settings</string>
    <string name="title_activity_main">Geocoding Demo</string>
    <string name="str_btn_find">Find</string>
    <string name="hnt_et_location">Enter location</string>
</resources>


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


<LinearLayout 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"
    android:orientation="vertical" >

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/btn_find"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/str_btn_find"
            android:layout_alignParentRight="true" />

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

    </RelativeLayout>

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

</LinearLayout>

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


11. Create a class namely LocationOverlay in the file src/in/wptrafficanalyzer/locationgeocoding/LocationOverlay.java


package in.wptrafficanalyzer.locationgeocoding;

import java.util.ArrayList;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.widget.Toast;

import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.OverlayItem;

public class LocationOverlay extends ItemizedOverlay<OverlayItem> {

    private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
    private Context mContext;

    public LocationOverlay(Drawable defaultMarker,Context context) {
        super(boundCenterBottom(defaultMarker));
        mContext = context;

    }

    // 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()
    }

    @Override
    protected boolean onTap(int arg0) {
        // Getting the tapped item
        OverlayItem item = getItem(arg0);

        Toast.makeText(mContext, item.getSnippet(), Toast.LENGTH_SHORT).show();
        return true;
    }
}


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


package in.wptrafficanalyzer.locationgeocoding;

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

import android.graphics.drawable.Drawable;
import android.location.Address;
import android.location.Geocoder;
import android.os.AsyncTask;
import android.os.Bundle;
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.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 {

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

        // Getting reference to btn_find of the layout activity_main
        Button btn_find = (Button) findViewById(R.id.btn_find);

        // Defining button click event listener for the find button
        OnClickListener findClickListener = new OnClickListener() {
            @Override
            public void onClick(View v) {
                // Getting reference to EditText to get the user input location
                EditText etLocation = (EditText) findViewById(R.id.et_location);

                // Getting user input location
                String location = etLocation.getText().toString();

                if(location!=null && !location.equals("")){
                    new GeocoderTask().execute(location);
                }
            }
        };

        // Setting button click event listener for the find button
        btn_find.setOnClickListener(findClickListener);
    }

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

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

    // An AsyncTask class for accessing the GeoCoding Web Service
    private class GeocoderTask extends AsyncTask<String, Void, List<Address>>{

        @Override
        protected List<Address> doInBackground(String... locationName) {
            // Creating an instance of Geocoder class
            Geocoder geocoder = new Geocoder(getBaseContext());
            List<Address> addresses = null;

            try {
                // Getting a maximum of 3 Address that matches the input text
                addresses = geocoder.getFromLocationName(locationName[0], 3);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return addresses;
        }

        @Override
        protected void onPostExecute(List<Address> addresses) {

            // Getting Reference to MapView of the layout activity_main
            MapView mapView = (MapView) findViewById(R.id.map_view);

            // Setting ZoomControls
            mapView.setBuiltInZoomControls(true);

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

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

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

            // Creating an ItemizedOverlay
            LocationOverlay locationOverlay = new LocationOverlay(drawable,getBaseContext());

            // Clearing the overlays
            overlays.clear();

            if(addresses==null || addresses.size()==0){
                Toast.makeText(getBaseContext(), "No Location found", Toast.LENGTH_SHORT).show();

                // Redraws the map to clear the overlays
                mapView.invalidate();
            }

            // Adding Markers on Google Map for each matching address
            for(int i=0;i<addresses.size();i++){

                Address address = (Address) addresses.get(i);

                // Creating an instance of GeoPoint, to display in Google Map
                GeoPoint p = new GeoPoint(
                                            (int)(address.getLatitude()*1E6),
                                            (int)(address.getLongitude()*1E6)
                                        );

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

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

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

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

                // Locate the first location
                if(i==0)
                    mc.animateTo(p);
            }

            // Redraws the map
            mapView.invalidate();
        }
    }
}

13. Update the file AndroidManifest.xml


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="in.wptrafficanalyzer.locationgeocoding"
    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

Displaying the locations returned from Geocoding Web Service in Google APIs Emulator ( API Level 4 )

Figure 5 : Displaying the locations returned from Geocoding Web Service 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: , , , , , , ,

13 Responses to Android Geocoding – Showing User Input Location on Google Map

  1. Lee Nolasco on November 28, 2012 at 10:18 pm

    I think the source code has some missing files

    • george on November 28, 2012 at 10:49 pm

      Probably you may have run this application in Android Virtual Device. If so, try to run this application in Google APIs Emulator or in a real device with API level >= 4

      • Lee Nolasco on November 30, 2012 at 3:35 pm

        my bad sir, my eclipse just had an error loading resources. I used this project as a refenrence for my project but instead of getting the location from a edittext, mine is coming from a textview but i am having an error in “new GeocoderTask().execute(hosname);” red line under execute. any ideas on how to fix this?

      • Rizal on December 18, 2012 at 4:54 am

        I have some problem if I run this application with API level >=4. What’s the problem?

  2. siti on December 7, 2012 at 9:21 am

    the application stop when i push the button “find”

    • george on December 7, 2012 at 9:25 am

      Are you getting any error messages in LogCat?

  3. kelvin on December 10, 2012 at 10:29 am

    sir,,when i press find button force close occurs??
    i used google api 2.2 map avd..
    plz fix..
    thank..
    error in logcat are there??

    FATAL EXCEPTION: main
    java.lang.NullPointerException
    at com.locationsearch.LocationsearchActivity$GeocoderTask.onPostExecut(LocationsearchActivity.java:107)
    at com.locationsearch.LocationsearchActivity$GeocoderTask.onPostExecute(LocationsearchActivity.java:1)
    at android.os.AsyncTask.finish(AsyncTask.java:417)
    at android.os.AsyncTask.access$300(AsyncTask.java:127)
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:429)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:123)
    at android.app.ActivityThread.main(ActivityThread.java:4627)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:521)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
    at dalvik.system.NativeStart.main(Native Method)
    I/Process(304): Sending signal. PID: 304 SIG: 9

  4. Devendar on December 11, 2012 at 11:28 pm

    12-11 12:56:57.815: E/AndroidRuntime(800): FATAL EXCEPTION: main
    12-11 12:56:57.815: E/AndroidRuntime(800): java.lang.NullPointerException
    12-11 12:56:57.815: E/AndroidRuntime(800): at in.wptrafficanalyzer.locationgeocoding.MainActivity$GeocoderTask.onPostExecute(MainActivity.java:120)
    12-11 12:56:57.815: E/AndroidRuntime(800): at in.wptrafficanalyzer.locationgeocoding.MainActivity$GeocoderTask.onPostExecute(MainActivity.java:1)
    12-11 12:56:57.815: E/AndroidRuntime(800): at android.os.AsyncTask.finish(AsyncTask.java:417)
    12-11 12:56:57.815: E/AndroidRuntime(800): at android.os.AsyncTask.access$300(AsyncTask.java:127)
    12-11 12:56:57.815: E/AndroidRuntime(800): at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:429)
    12-11 12:56:57.815: E/AndroidRuntime(800): at android.os.Handler.dispatchMessage(Handler.java:99)
    12-11 12:56:57.815: E/AndroidRuntime(800): at android.os.Looper.loop(Looper.java:130)
    12-11 12:56:57.815: E/AndroidRuntime(800): at android.app.ActivityThread.main(ActivityThread.java:3683)
    12-11 12:56:57.815: E/AndroidRuntime(800): at java.lang.reflect.Method.invokeNative(Native Method)
    12-11 12:56:57.815: E/AndroidRuntime(800): at java.lang.reflect.Method.invoke(Method.java:507)
    12-11 12:56:57.815: E/AndroidRuntime(800): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
    12-11 12:56:57.815: E/AndroidRuntime(800): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
    12-11 12:56:57.815: E/AndroidRuntime(800): at dalvik.system.NativeStart.main(Native Method)
    12-11 12:57:04.905: I/Process(800): Sending signal. PID: 800 SIG: 9

  5. mala on February 21, 2013 at 3:24 am

    thank you so much..
    i had been looking multiple site for the tutorial on this topic..
    but ur code is the best

  6. somish on June 3, 2013 at 11:56 am

    GeocoderTask not working ..have error

    • george on June 3, 2013 at 1:55 pm

      Hi Somish,
      Can you please provide us error details (mainly from Logcat)?

  7. kelvz on October 20, 2014 at 11:33 pm

    hi is it possible that i will lock the map into a single city ?

  8. Maysa Khamis on April 1, 2015 at 1:49 am

    android studio can’t import import com.google.android.maps.ItemizedOverlay;
    can’t be solved ??

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