In this article, we will develop an Android application which facilitates users to select a place from AutoCompleteTextView and that place will be marked in Google Map Android API V2.
This application is developed in Eclipse (4.2.1) with ADT plugin (21.0.0) and Android SDK (21.0.0) and tested in a real device with Android 2.3.6 ( GingerBread ).
1. Create a new Android application project namely “LocationAutoGoogleMapV2″
2. Configure the project
3. Design application launcher icon
4. Create a blank activity
5. Enter MainActivity details
6. Download and configure Google Play Services Library in Eclips
Google Map for Android is now integrated with Google Play Services. So we need to set up Google Play Service Library for developing Google Map application in Android.
Please follow the given below link to setup Google Play Service library in Eclipse.
http://developer.android.com/google/play-services/setup.html
Note : Please ensure that, the latest version of Google Play Service Library is installed
7. Add Google Play Services Library to this project
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. Get the API key for Google Places API
We can create API key for Google Place API by clicking “Create new Browser key” available at the “API Access” pane of the Google console URL : http://code.google.com/apis/console.
Also ensure that, “Places API” is enabled in the “Services” pane of the Google console.
10. 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 “
11. Update the file res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">LocationAutoGoogleMapV2</string> <string name="action_settings">Settings</string> <string name="hello_world">Hello world!</string> <string name="str_atv_places">Enter Place Here</string> </resources>
12. Create a class namely “CustomAutoCompleteTextView” in the file src/in/wptrafficanalyzer/locationautogooglemapv2/CustomAutoCompleteTextView.java
package in.wptrafficanalyzer.locationautogooglemapv2; import java.util.HashMap; import android.content.Context; import android.util.AttributeSet; import android.widget.AutoCompleteTextView; /** Customizing AutoCompleteTextView to return Place Description * corresponding to the selected item */ public class CustomAutoCompleteTextView extends AutoCompleteTextView { public CustomAutoCompleteTextView(Context context, AttributeSet attrs) { super(context, attrs); } /** Returns the Place Description corresponding to the selected item */ @Override protected CharSequence convertSelectionToString(Object selectedItem) { /** Each item in the autocompetetextview suggestion list is a hashmap object */ HashMap<String, String> hm = (HashMap<String, String>) selectedItem; return hm.get("description"); } }
13. 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" > <in.wptrafficanalyzer.locationautogooglemapv2.CustomAutoCompleteTextView android:id="@+id/atv_places" android: layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:hint="@string/str_atv_places" android:singleLine="true" /> <fragment android:id="@+id/map" android:layout_width="wrap_content" android:layout_height="wrap_content" class="com.google.android.gms.maps.SupportMapFragment" android:layout_below="@id/atv_places" /> </RelativeLayout>
14. Create a new class namely “PlaceJSONParser” in the file src/in/wptrafficanalyzer/locationautogooglemapv2/PlaceJSONParser.java
package in.wptrafficanalyzer.locationautogooglemapv2; 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 PlaceJSONParser { /** 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("predictions"); } 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 id=""; String reference=""; String description=""; try { description = jPlace.getString("description"); id = jPlace.getString("id"); reference = jPlace.getString("reference"); place.put("description", description); place.put("_id",id); place.put("reference",reference); } catch (JSONException e) { e.printStackTrace(); } return place; } }
15. Create a new class namely “PlaceDetailsJSONParser” in the file src/in/wptrafficanalyzer/locationautogooglemapv2/PlaceDetailsJSONParser.java
package in.wptrafficanalyzer.locationautogooglemapv2; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.json.JSONException; import org.json.JSONObject; public class PlaceDetailsJSONParser { /** Receives a JSONObject and returns a list */ public List<HashMap<String,String>> parse(JSONObject jObject){ Double lat = Double.valueOf(0); Double lng = Double.valueOf(0); HashMap<String, String> hm = new HashMap<String, String>(); List<HashMap<String, String>> list = new ArrayList<HashMap<String,String>>(); try { lat = (Double)jObject.getJSONObject("result").getJSONObject("geometry").getJSONObject("location").get("lat"); lng = (Double)jObject.getJSONObject("result").getJSONObject("geometry").getJSONObject("location").get("lng"); } catch (JSONException e) { e.printStackTrace(); }catch(Exception e){ e.printStackTrace(); } hm.put("lat", Double.toString(lat)); hm.put("lng", Double.toString(lng)); list.add(hm); return list; } }
16. Update the class “MainActivity” in the file src/in/wptrafficanalyzer/locationautogooglemapv2/MainActivity.java
package in.wptrafficanalyzer.locationautogooglemapv2; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; 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.text.Editable; import android.text.TextWatcher; import android.util.Log; import android.view.Menu; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.AutoCompleteTextView; import android.widget.ListView; import android.widget.SimpleAdapter; import com.google.android.gms.maps.CameraUpdate; 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 { AutoCompleteTextView atvPlaces; DownloadTask placesDownloadTask; DownloadTask placeDetailsDownloadTask; ParserTask placesParserTask; ParserTask placeDetailsParserTask; GoogleMap googleMap; final int PLACES=0; final int PLACES_DETAILS=1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Getting a reference to the AutoCompleteTextView atvPlaces = (AutoCompleteTextView) findViewById(R.id.atv_places); atvPlaces.setThreshold(1); // Adding textchange listener atvPlaces.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // Creating a DownloadTask to download Google Places matching "s" placesDownloadTask = new DownloadTask(PLACES); // Getting url to the Google Places Autocomplete api String url = getAutoCompleteUrl(s.toString()); // Start downloading Google Places // This causes to execute doInBackground() of DownloadTask class placesDownloadTask.execute(url); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { // TODO Auto-generated method stub } @Override public void afterTextChanged(Editable s) { // TODO Auto-generated method stub } }); // Setting an item click listener for the AutoCompleteTextView dropdown list atvPlaces.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int index, long id) { ListView lv = (ListView) arg0; SimpleAdapter adapter = (SimpleAdapter) arg0.getAdapter(); HashMap<String, String> hm = (HashMap<String, String>) adapter.getItem(index); // Creating a DownloadTask to download Places details of the selected place placeDetailsDownloadTask = new DownloadTask(PLACES_DETAILS); // Getting url to the Google Places details api String url = getPlaceDetailsUrl(hm.get("reference")); // Start downloading Google Place Details // This causes to execute doInBackground() of DownloadTask class placeDetailsDownloadTask.execute(url); } }); } private String getAutoCompleteUrl(String place){ // Obtain browser key from https://code.google.com/apis/console String key = "key=YOUR_API_KEY"; // place to be be searched String input = "input="+place; // place type to be searched String types = "types=geocode"; // Sensor enabled String sensor = "sensor=false"; // Building the parameters to the web service String parameters = input+"&"+types+"&"+sensor+"&"+key; // Output format String output = "json"; // Building the url to the web service String url = "https://maps.googleapis.com/maps/api/place/autocomplete/"+output+"?"+parameters; return url; } private String getPlaceDetailsUrl(String ref){ // Obtain browser key from https://code.google.com/apis/console String key = "key=YOUR_API_KEY"; // reference of place String reference = "reference="+ref; // Sensor enabled String sensor = "sensor=false"; // Building the parameters to the web service String parameters = reference+"&"+sensor+"&"+key; // Output format String output = "json"; // Building the url to the web service String url = "https://maps.googleapis.com/maps/api/place/details/"+output+"?"+parameters; return url; } /** A method to download json data from 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; } // Fetches data from url passed private class DownloadTask extends AsyncTask<String, Void, String>{ private int downloadType=0; // Constructor public DownloadTask(int type){ this.downloadType = type; } @Override protected String doInBackground(String... url) { // For storing data from web service String data = ""; try{ // Fetching the data from web service data = downloadUrl(url[0]); }catch(Exception e){ Log.d("Background Task",e.toString()); } return data; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); switch(downloadType){ case PLACES: // Creating ParserTask for parsing Google Places placesParserTask = new ParserTask(PLACES); // Start parsing google places json data // This causes to execute doInBackground() of ParserTask class placesParserTask.execute(result); break; case PLACES_DETAILS : // Creating ParserTask for parsing Google Places placeDetailsParserTask = new ParserTask(PLACES_DETAILS); // Starting Parsing the JSON string // This causes to execute doInBackground() of ParserTask class placeDetailsParserTask.execute(result); } } } /** A class to parse the Google Places in JSON format */ private class ParserTask extends AsyncTask<String, Integer, List<HashMap<String,String>>>{ int parserType = 0; public ParserTask(int type){ this.parserType = type; } @Override protected List<HashMap<String, String>> doInBackground(String... jsonData) { JSONObject jObject; List<HashMap<String, String>> list = null; try{ jObject = new JSONObject(jsonData[0]); switch(parserType){ case PLACES : PlaceJSONParser placeJsonParser = new PlaceJSONParser(); // Getting the parsed data as a List construct list = placeJsonParser.parse(jObject); break; case PLACES_DETAILS : PlaceDetailsJSONParser placeDetailsJsonParser = new PlaceDetailsJSONParser(); // Getting the parsed data as a List construct list = placeDetailsJsonParser.parse(jObject); } }catch(Exception e){ Log.d("Exception",e.toString()); } return list; } @Override protected void onPostExecute(List<HashMap<String, String>> result) { switch(parserType){ case PLACES : String[] from = new String[] { "description"}; int[] to = new int[] { android.R.id.text1 }; // Creating a SimpleAdapter for the AutoCompleteTextView SimpleAdapter adapter = new SimpleAdapter(getBaseContext(), result, android.R.layout.simple_list_item_1, from, to); // Setting the adapter atvPlaces.setAdapter(adapter); break; case PLACES_DETAILS : HashMap<String, String> hm = result.get(0); // Getting latitude from the parsed data double latitude = Double.parseDouble(hm.get("lat")); // Getting longitude from the parsed data double longitude = Double.parseDouble(hm.get("lng")); // Getting reference to the SupportMapFragment of the activity_main.xml SupportMapFragment fm = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); // Getting GoogleMap from SupportMapFragment googleMap = fm.getMap(); LatLng point = new LatLng(latitude, longitude); CameraUpdate cameraPosition = CameraUpdateFactory.newLatLng(point); CameraUpdate cameraZoom = CameraUpdateFactory.zoomBy(5); // Showing the user input location in the Google Map googleMap.moveCamera(cameraPosition); googleMap.animateCamera(cameraZoom); MarkerOptions options = new MarkerOptions(); options.position(point); options.title("Position"); options.snippet("Latitude:"+latitude+",Longitude:"+longitude); // Adding the marker in the Google Map googleMap.addMarker(options); break; } } } @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; } }
Note : Replace “YOUR_API_KEY” at the lines 114 and 140 with the API key obtained in Step 9
17. 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.locationautogooglemapv2" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <uses-permission android:name="android.permission.INTERNET"/> <permission android:name="in.wptrafficanalyzer.locationautogooglemapv2.permission.MAPS_RECEIVE" android:protectionLevel="signature" /> <uses-permission android:name="in.wptrafficanalyzer.locationautogooglemapv2.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.locationautogooglemapv2.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 : Replace “YOUR_API_KEY” at the 45 with the API key obtained in Step 8
18. Screenshots of the application
19. Download Source Code


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
your article is very very helpful. i really appreciate for your article!! anyway, i have a question. didnt it need this -> class=”com.google.android.gms.maps.SupportMapFragment”<- under <fragment
android:id="@+id/map"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/atv_places" <- here ?
plz, recomment~
Yes, that is needed.
Thank you for reporting this and corrected it in the article.
no thx! all your tutorial is always helful!
Thanks for the wonderful tutorial.
I have one question:why it always mark the same wrong place no matter what place I input
So sorry for disturbing you. I just found I forgot one of the brower KEY
Thanks for Your Tutorial
am not getting any kind of places in autocompletetextview am confused at generating browser key. There is no google maps in our website this is the problem or not.
When using Google Places API, Users with an API key are allowed 1 000 requests per 24 hour period. after exceeding this limit, we got “OVER_QUERY_LIMIT” error.
How could i handle this in your code ?
Hello sir,
I am using this project in my app. but i am getting only map. I am not getting any auto suggestions when i type any place. please guide
I’m getting the same problem
Same here, any solution?
check your browser key. Make sure you create new browser key, then for the reference leave it blank so that it will referred any.
Hello,
Thanks very much for this example.
I succesfully implemented it in my app.
There is one problem however.
The SimpleAdapter has a filter which breaks words apart. So for instance if you press space after a word, no more results are showing. Did you find a workaround this?
Sir I have not my own website then how i generate the browser key
i went to use browser key in android application
this is really very helpful example .
but is this possible to use autocomplete edittext for two marker and and find the driving route between that markers??
please recomment for this……
12-18 00:24:53.863: E/AndroidRuntime(738): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.googlemap/com.example.googlemap.MainActivity}: android.view.InflateException: Binary XML file line #15: Error inflating class fragment
Hello sir,
I am using this project in my app. but i am getting only map. I am not getting any auto suggestions when i type any place. please guide me
i want to add 2 autocomplete text view in which user enters source and destinations and when user preses find directions button then the directions/route/path from source to destination should be displayed on map , how to do that, kindly help , its really urgent
hi sir. The tutorial is very useful!
I run the project. It’s work well. But autocomplete text just correct first time it suggestion. When i try the second time it make wrong position,and I dont know why?
Great tutorial. Thanks for this.
Can you please confirm, that you are fine with the code of this tutorial being used in one’s own apps free of charge. I am asking since there is no Licence file in the code download. This would be a great help.
Thanks,
Rainer
Hello Sir,
The tutorial is very useful!, but my autocomplete text view not working, i am adding brwser key(goolgle place Map android(enable) -> api key -> Credentials -> browser key with empty)
But, autocomplete text view not running .
please. tell me what happen.
Sir please what is the difference between the Browser key and the Api key
are they the same
Hello sir,
can you please tell me how to show the search result list in a listview.
you show it in a default simple_list_item_1 but i want to show it in an own created list view.
please help me sir