In this article we will develop an Android Application which displays a set of nearby places of current location in Google Map according to the type entered in the Spinner widget.
This application makes use of Google services like Google Map Android API V2 and Google Places API.
This application is developed in Eclipse (4.2.1) with ADT plugin (23.0.0) and Android SDK (23.0.0) and tested in a real device with Android 4.1.0 .
Follow the Google Map Version 2 Tutorial to Understand This.
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
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.
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 “
Here is the MainActivity:
package com.example.googlemap; 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.app.Dialog; import android.location.Criteria; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; 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.ArrayAdapter; import android.widget.Button; import android.widget.Spinner; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesUtil; 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 implements LocationListener{ GoogleMap mGoogleMap; Spinner mSprPlaceType; String[] mPlaceType=null; String[] mPlaceTypeName=null; double mLatitude=0; double mLongitude=0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Array of place types mPlaceType = getResources().getStringArray(R.array.place_type); // Array of place type names mPlaceTypeName = getResources().getStringArray(R.array.place_type_name); // Creating an array adapter with an array of Place types // to populate the spinner ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, mPlaceTypeName); // Getting reference to the Spinner mSprPlaceType = (Spinner) findViewById(R.id.spr_place_type); // Setting adapter on Spinner to set place types mSprPlaceType.setAdapter(adapter); Button btnFind; // Getting reference to Find Button btnFind = ( Button ) findViewById(R.id.btn_find); // Getting Google Play availability status int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getBaseContext()); if(status!=ConnectionResult.SUCCESS){ // Google Play Services are not available int requestCode = 10; Dialog dialog = GooglePlayServicesUtil.getErrorDialog(status, this, requestCode); dialog.show(); }else { // Google Play Services are available // Getting reference to the SupportMapFragment SupportMapFragment fragment = ( SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); // Getting Google Map mGoogleMap = fragment.getMap(); // Enabling MyLocation in Google Map mGoogleMap.setMyLocationEnabled(true); // Getting LocationManager object from System Service LOCATION_SERVICE LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); // Creating a criteria object to retrieve provider Criteria criteria = new Criteria(); // Getting the name of the best provider String provider = locationManager.getBestProvider(criteria, true); // Getting Current Location From GPS Location location = locationManager.getLastKnownLocation(provider); if(location!=null){ onLocationChanged(location); } locationManager.requestLocationUpdates(provider, 20000, 0, this); // Setting click event lister for the find button btnFind.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { int selectedPosition = mSprPlaceType.getSelectedItemPosition(); String type = mPlaceType[selectedPosition]; StringBuilder sb = new StringBuilder("https://maps.googleapis.com/maps/api/place/nearbysearch/json?"); sb.append("location="+mLatitude+","+mLongitude); sb.append("&radius=5000"); sb.append("&types="+type); sb.append("&sensor=true"); sb.append("&key=ENTER_YOUR_KEY_HERE"); // Creating a new non-ui thread task to download Google place json data PlacesTask placesTask = new PlacesTask(); // Invokes the "doInBackground()" method of the class PlaceTask placesTask.execute(sb.toString()); } }); } } /** 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; } /** A class, to download Google Places */ private class PlacesTask 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){ ParserTask parserTask = new ParserTask(); // Start parsing the Google places in JSON format // Invokes the "doInBackground()" method of the class ParseTask parserTask.execute(result); } } /** A class to parse the Google Places in JSON format */ private 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; PlaceJSONParser placeJsonParser = new PlaceJSONParser(); try{ jObject = new JSONObject(jsonData[0]); /** Getting the parsed data as a List construct */ places = placeJsonParser.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 mGoogleMap.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("place_name"); // Getting vicinity String vicinity = hmPlace.get("vicinity"); LatLng latLng = new LatLng(lat, lng); // Setting the position for the marker markerOptions.position(latLng); // Setting the title for the marker. //This will be displayed on taping the marker markerOptions.title(name + " : " + vicinity); // Placing a marker on the touched position mGoogleMap.addMarker(markerOptions); } } } @Override public void onLocationChanged(Location location) { mLatitude = location.getLatitude(); mLongitude = location.getLongitude(); LatLng latLng = new LatLng(mLatitude, mLongitude); mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng)); mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(12)); } @Override public void onProviderDisabled(String provider) { // TODO Auto-generated method stub } @Override public void onProviderEnabled(String provider) { // TODO Auto-generated method stub } @Override public void onStatusChanged(String provider, int status, Bundle extras) { // TODO Auto-generated method stub } }
Replace ENTER_YOUR_KEY_HERE with your Google Places Browser key for Any Refferer
Here is the code for PlaceJSONParser.java:
package com.example.googlemap; 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("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 placeName = "-NA-"; String vicinity="-NA-"; String latitude=""; String longitude=""; try { // Extracting Place name, if available if(!jPlace.isNull("name")){ placeName = jPlace.getString("name"); } // Extracting Place Vicinity, if available if(!jPlace.isNull("vicinity")){ vicinity = jPlace.getString("vicinity"); } latitude = jPlace.getJSONObject("geometry").getJSONObject("location").getString("lat"); longitude = jPlace.getJSONObject("geometry").getJSONObject("location").getString("lng"); place.put("place_name", placeName); place.put("vicinity", vicinity); place.put("lat", latitude); place.put("lng", longitude); } catch (JSONException e) { e.printStackTrace(); } return place; } }
Update the String.xml file as follows:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">MyPlaces</string> <string name="hello_world">Hello world!</string> <string name="menu_settings">Settings</string> <string name="str_btn_find">Find</string> <string-array name="place_type"> <item>airport</item> <item>atm</item> <item>bank</item> <item>bus_station</item> <item>church</item> <item>doctor</item> <item>hospital</item> <item>mosque</item> <item>movie_theater</item> <item>hindu_temple</item> <item>restaurant</item> </string-array> <string-array name="place_type_name"> <item>Airport</item> <item>ATM</item> <item>Bank</item> <item>Bus Station</item> <item>Church</item> <item>Doctor</item> <item>Hospital</item> <item>Mosque</item> <item>Movie Theater</item> <item>Hindu Temple</item> <item>Restaurant</item> </string-array> </resources>
Update the AndroidManifest.xml file:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.googlemap" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="16" /> <permission android:name="com.example.googlemap.permission.MAPS_RECEIVE" android:protectionLevel="signature" /> <uses-permission android:name="com.example.googlemap.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" /> <!-- Network State Permissions --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- Access 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="com.example.googlemap.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.gms.version" android:value="@integer/google_play_services_version" /> <meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="ENTER_YOUR_KEY_HERE" /> </application> </manifest>
ENTER_YOUR_KEY_HERE replace with your Google Map Version 2 Android Key
Here is Some Screen Shots of The Project:
Click on this image to download the Full Source Code
Click On This Image to Download .APK File
Happy Coding..!