Showing nearby places using Google Places API

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:

 

c1             c2            c3

 

 

c4              c5           c6

 

 

Click on this image to download the Full Source Code

z

Click On This Image to Download .APK File

z

Happy Coding..!

Leave a comment