Showing nearby places and place details using Google Places API and Google Maps Android API V2

June 7, 2013
By

In this article, we are going to develop an Android application which shows nearby places of current location in Google Maps Android API V2. On taping the InfoWindow of the marker, the details of the corresponding place will be displayed in a separate activity.



This application makes use of Google services like Google Maps Android API V2, Google Places API and Google Place Details API.

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.0.4 ( Ice Cream Sandwich ).



1. Create a new Android application project namely “LocationPlaceDetailsV2″

Create new Android application project

Figure 1 : Create new Android application project


2. Configure the project

Configuring the application project

Figure 2 : Configuring the application project


3. Design application launcher icon

Design application launcher icon

Figure 3 : Design application launcher icon


4. Create a blank activity

Create a blank activity

Figure 4 : Create a blank activity


5. Enter MainActivity details

Enter MainActivity details

Figure 5 : Enter MainActivity details


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


7. Add Google Play Services Library to this project

Link Google Play Services library to this project

Figure 6 : Link 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">LocationPlaceDetailsV2</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</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>


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

    <Spinner
        android:id="@+id/spr_place_type"
        android:layout_width="wrap_content"
        android:layout_height="60dp"
        android:layout_alignParentTop="true" />

    <Button
        android:id="@+id/btn_find"
        android:layout_width="wrap_content"
        android:layout_height="60dp"
        android:layout_alignParentTop="true"
        android:layout_toRightOf="@id/spr_place_type"
        android:text="@string/str_btn_find" />

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/map"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/spr_place_type"
        class="com.google.android.gms.maps.SupportMapFragment" />

</RelativeLayout>


13. Create a layout file res/layout/activity_place_details.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <WebView
        android:id="@+id/wv_place_details"
        android:layout_width="fill_parent"
        android:layout_height="match_parent" />
</LinearLayout>


14. Create a new class namely “PlaceJSONParser” in the file src/in/wptrafficanalyzer/locationplacedetailsv2/PlaceJSONParser.java


package in.wptrafficanalyzer.locationplacedetailsv2;

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="";
        String reference="";

        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");
            reference = jPlace.getString("reference");

            place.put("place_name", placeName);
            place.put("vicinity", vicinity);
            place.put("lat", latitude);
            place.put("lng", longitude);
            place.put("reference", reference);

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


15. Create a new class namely “PlaceDetailsJSONParser” in the file src/in/wptrafficanalyzer/locationnearby/PlaceDetailsJSONParser.java


package in.wptrafficanalyzer.locationplacedetailsv2;

import java.util.HashMap;

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

public class PlaceDetailsJSONParser {

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

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

    /** Parsing the Place Details Object object */
    private HashMap<String, String> getPlaceDetails(JSONObject jPlaceDetails){

        HashMap<String, String> hPlaceDetails = new HashMap<String, String>();

        String name = "-NA-";
        String icon = "-NA-";
        String vicinity="-NA-";
        String latitude="";
        String longitude="";
        String formatted_address="-NA-";
        String formatted_phone="-NA-";
        String website="-NA-";
        String rating="-NA-";
        String international_phone_number="-NA-";
        String url="-NA-";

        try {
            // Extracting Place name, if available
            if(!jPlaceDetails.isNull("name")){
                name = jPlaceDetails.getString("name");
            }

            // Extracting Icon, if available
            if(!jPlaceDetails.isNull("icon")){
                icon = jPlaceDetails.getString("icon");
            }

            // Extracting Place Vicinity, if available
            if(!jPlaceDetails.isNull("vicinity")){
                vicinity = jPlaceDetails.getString("vicinity");
            }

            // Extracting Place formatted_address, if available
            if(!jPlaceDetails.isNull("formatted_address")){
                formatted_address = jPlaceDetails.getString("formatted_address");
            }

            // Extracting Place formatted_phone, if available
            if(!jPlaceDetails.isNull("formatted_phone_number")){
                formatted_phone = jPlaceDetails.getString("formatted_phone_number");
            }

            // Extracting website, if available
            if(!jPlaceDetails.isNull("website")){
                website = jPlaceDetails.getString("website");
            }

            // Extracting rating, if available
            if(!jPlaceDetails.isNull("rating")){
                 rating = jPlaceDetails.getString("rating");
            }

            // Extracting rating, if available
            if(!jPlaceDetails.isNull("international_phone_number")){
                international_phone_number = jPlaceDetails.getString("international_phone_number");
            }

            // Extracting url, if available
            if(!jPlaceDetails.isNull("url")){
                url = jPlaceDetails.getString("url");
            }

            latitude = jPlaceDetails.getJSONObject("geometry").getJSONObject("location").getString("lat");
            longitude = jPlaceDetails.getJSONObject("geometry").getJSONObject("location").getString("lng");

            hPlaceDetails.put("name", name);
            hPlaceDetails.put("icon", icon);
            hPlaceDetails.put("vicinity", vicinity);
            hPlaceDetails.put("lat", latitude);
            hPlaceDetails.put("lng", longitude);
            hPlaceDetails.put("formatted_address", formatted_address);
            hPlaceDetails.put("formatted_phone", formatted_phone);
            hPlaceDetails.put("website", website);
            hPlaceDetails.put("rating", rating);
            hPlaceDetails.put("international_phone_number", international_phone_number);
            hPlaceDetails.put("url", url);

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


16. Create a new class “PlaceDetailsActivity” in the file src/in/wptrafficanalyzer/locationplacedetailsv2/PlaceDetailsActivity.java


package in.wptrafficanalyzer.locationplacedetailsv2;

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 org.json.JSONObject;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.webkit.WebView;

public class PlaceDetailsActivity extends Activity {
    WebView mWvPlaceDetails;

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_place_details);

        // Getting reference to WebView ( wv_place_details ) of the layout activity_place_details
        mWvPlaceDetails = (WebView) findViewById(R.id.wv_place_details);

        mWvPlaceDetails.getSettings().setUseWideViewPort(false);

        // Getting place reference from the map
        String reference = getIntent().getStringExtra("reference");

        StringBuilder sb = new StringBuilder("https://maps.googleapis.com/maps/api/place/details/json?");
        sb.append("reference="+reference);
        sb.append("&sensor=true");
        sb.append("&key=YOUR_BROWSER_API_KEY_FOR_PLACES");

        // Creating a new non-ui thread task to download Google place details
        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 Place Details */
    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 place details in JSON format
            // Invokes the "doInBackground()" method of the class ParseTask
            parserTask.execute(result);
        }
    }

    /** A class to parse the Google Place Details in JSON format */
    private class ParserTask extends AsyncTask<String, Integer, HashMap<String,String>>{

        JSONObject jObject;

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

            HashMap<String, String> hPlaceDetails = null;
            PlaceDetailsJSONParser placeDetailsJsonParser = new PlaceDetailsJSONParser();

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

                // Start parsing Google place details in JSON format
                hPlaceDetails = placeDetailsJsonParser.parse(jObject);

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

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

            String name = hPlaceDetails.get("name");
            String icon = hPlaceDetails.get("icon");
            String vicinity = hPlaceDetails.get("vicinity");
            String lat = hPlaceDetails.get("lat");
            String lng = hPlaceDetails.get("lng");
            String formatted_address = hPlaceDetails.get("formatted_address");
            String formatted_phone = hPlaceDetails.get("formatted_phone");
            String website = hPlaceDetails.get("website");
            String rating = hPlaceDetails.get("rating");
            String international_phone_number = hPlaceDetails.get("international_phone_number");
            String url = hPlaceDetails.get("url");

            String mimeType = "text/html";
            String encoding = "utf-8";

            String data = "<html>"+
                          "<body><img style='float:left' src="+icon+" /><h1><center>"+name+"</center></h1>" +
                          "<br style='clear:both' />" +
                          "<hr />"+
                          "<p>Vicinity : " + vicinity + "</p>" +
                          "<p>Location : " + lat + "," + lng + "</p>" +
                          "<p>Address : " + formatted_address + "</p>" +
                          "<p>Phone : " + formatted_phone + "</p>" +
                          "<p>Website : " + website + "</p>" +
                          "<p>Rating : " + rating + "</p>" +
                          "<p>International Phone : " + international_phone_number + "</p>" +
                          "<p>URL : <a href='" + url + "'>" + url + "</p>" +
                          "</body></html>";

            // Setting the data in WebView
            mWvPlaceDetails.loadDataWithBaseURL("", data, mimeType, encoding, "");
        }
    }
}


17. Update the class “MainActivity” in the file src/in/wptrafficanalyzer/locationplacedetailsv2/MainActivity.java

package in.wptrafficanalyzer.locationplacedetailsv2;

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.content.Intent;
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.GoogleMap.OnInfoWindowClickListener;
import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
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;

    HashMap<String, String> mMarkerPlaceLink = new HashMap<String, String>();

    @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);

            mGoogleMap.setOnInfoWindowClickListener(new OnInfoWindowClickListener() {

                @Override
                public void onInfoWindowClick(Marker arg0) {
                    Intent intent = new Intent(getBaseContext(), PlaceDetailsActivity.class);
                    String reference = mMarkerPlaceLink.get(arg0.getId());
                    intent.putExtra("reference", reference);

                    // Starting the Place Details Activity
                    startActivity(intent);
                }
            });

            // 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=YOUR_BROWSER_API_KEY_FOR_PLACES");

                    // 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
                Marker m = mGoogleMap.addMarker(markerOptions);

                // Linking Marker id and place reference
                mMarkerPlaceLink.put(m.getId(), hmPlace.get("reference"));
            }
        }
    }

    @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;
    }

    @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
    }
}

18. 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.locationplacedetailsv2"
    android:versionCode="1"
    android:versionName="1.0" >

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

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

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

        <activity
            android:name="in.wptrafficanalyzer.locationplacedetailsv2.PlaceDetailsActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name=".PlaceDetails" />
                    <category android:name="android.intent.category.DEFAULT" />
                </intent-filter>
        </activity>

        <meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="YOUR_ANDROID_API_KEY"/>
    </application>
</manifest>


19. Screenshots of the application

Showing nearby doctors of the current location

Figure 7 : Showing nearby doctors of the current location

Showing place details on taping the InfoWindow

Figure 7 : Showing place details on taping the InfoWindow


20. Download 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: , , , ,

43 Responses to Showing nearby places and place details using Google Places API and Google Maps Android API V2

  1. Basribaz on June 10, 2013 at 2:31 pm

    not able to Indonesian territory

    • Kaustav Ghosh on February 25, 2014 at 2:51 pm

      Dear sir,
      Can you please tell me that are my BROWSER API KEY FOR PLACES and my Google API key are same??if not then how to generate a browser api key??

  2. chris on June 11, 2013 at 2:16 pm

    hello
    since i update adt no one map works

    have you got idea why???
    thank
    Chris

    • george on June 11, 2013 at 3:15 pm

      Hello Chris,

      Please do the following :

      * Open properties window by right clicking the project from project explorer

      * Select Java Build Path -> Order and Export tab

      * Ensure “Android Private Libraries” is checked

      * If unchecked, “check” it and click ok

      * Clean and Build the project and run the application

      • chris on June 12, 2013 at 11:30 am

        thanks,
        when i do it:
        the place of lib google play service isn’t at the good position and i don’t know how to put in ‘android depencies’ and ‘android private librairie’??
        for me it just in librairie as .jar
        in the project is in ‘referenced librairies’ path

        thanks
        chris

  3. MedO on June 11, 2013 at 9:27 pm

    how to activiate Places API
    they require Please provide additional information about your company or organization
    I don’t have a company

  4. Jack on June 11, 2013 at 10:20 pm

    Dear sir, I think the key word of tel number is “formatted_phone_number”

    • george on June 11, 2013 at 10:45 pm

      Hi Jack,
      According to the documentation, “formatted_phone_number” contains place’s telephone number in local format. Whereas the “international_phone_number” contains place’s telephone number in international format.

      • Jack on June 14, 2013 at 5:30 pm

        Dear sir, that not what I mean.
        Oh my poor English
        I mean the key word you use in the code above is “formatted_phone”, rather than “formatted_phone_number”.
        I found it because when I run the app, it always shows nothing of the phone number

        • george on June 14, 2013 at 6:12 pm

          Hi Jack,
          Thanks for reporting this.
          Now it is corrected in the article and in the source code.

  5. dianhosen on June 13, 2013 at 7:30 pm

    Hi, It is a nice tutorial. I’m trying to follow the tutorial …The map appears but the places are not there. Do we need to define more details the places somewhere in the code? Sorry if I’m a bit slow as a beginner…

  6. David on July 1, 2013 at 2:45 am

    Hi,

    The app crashes and I’m not sure why…
    My emulator doesn’t work so I try to run it and once I get the apk file, I email it to myself and install it on my Galaxy S2.
    However, after I load the app, it crashes within seconds…
    Any reason it may happen? I have both of the keys (Android Apps and browser apps) and inputted them in the correct locations.
    For the rest, I just copy-pasted.

    Also, where is all of the data taken from? perhaps I’m not connecting to the source or the database correctly.

    Thanks,
    David

    • David on July 1, 2013 at 4:29 am

      Hi again,

      Okay, I found the mistake and the app loads… however, I don’t see the map itself and the locations… any reason why it may happen?

      Thanks…

      • george on July 1, 2013 at 7:33 am

        Please check, you entered the correct places api and android api keys. Also ensure that Places API is enabled.

        • David on July 5, 2013 at 2:40 am

          I have two keys,
          “Key for Android apps”
          &
          “Key for browser apps”

          I entered the first one once in AndroidManifest.xml
          and the second one twice (one time in MainActivity.java and the second time in PlaceDetailsActivity.java).

          Did I miss anything?

          Thanks.

          • hieu on May 31, 2014 at 8:24 pm

            Can you tell me how to generate browser key, please?
            I register in https://code.google.com/apis/console/ but I don’t understand fill information in URL.

        • David on July 5, 2013 at 2:42 am

          And, how do I know that Places API is enabled?

          • David on July 5, 2013 at 5:50 am

            I think I was able to enable it through Google Developers… but I still see nothing…

          • george on July 5, 2013 at 5:58 am

            You can enable Place API via, https://code.google.com/apis/console/

        • David on July 6, 2013 at 8:52 pm

          I did enable Places API and it even asked me to create a Billing account…
          Now I have two APIs enables:
          Google Maps Android API v2
          and
          Places API

          • David on July 7, 2013 at 6:35 am

            Found my mistake…
            I was using the incorrect SHA1 value…

            thanks.

      • bonzo on November 13, 2013 at 1:43 pm

        Hey, I’m getting the same problem….my app also crashes when i run it on emulator or my galaxy grand…how did you solve your problem

        Thanks

    • Moath on April 30, 2014 at 5:25 am

      Hey, I’m getting the same problem….my app also crashes when i run it on emulator or my galaxy S2
      Can you Please tell me how did you solve your problem

  7. David on July 7, 2013 at 9:36 pm

    Hello again,

    I’m facing another problem… I now can see the map but I don’t see the locations… how do I enable the locations?
    Do I need to use my own database?

    Thanks

  8. Danny on July 13, 2013 at 9:51 pm

    Application crashed when I click on the name of the places.
    .wptrafficanalyzer.locationplacedetailsv2.PlaceDetailsActivity$ParserTask.onPostExecute(PlaceDetailsActivity.java:152)

  9. David on July 15, 2013 at 3:32 am

    Still struggling to get business places in action…
    I have all of the API codes set and Places API is enabled… what could be other reasons for this problem?
    I see the map and my current location, but that’s about it… I click ‘Find’ and nothing happens…

  10. Bob Sagget on August 4, 2013 at 8:02 am

    Thanks for the tutorial! The only problem I am having is that the app crashes when I click on a location’s name. Any idea why this might be happening?

    • george on August 4, 2013 at 8:11 am

      Are you getting any hint from logcat?

      • Bob Sagget on August 4, 2013 at 9:26 am

        Yes! logcat helped and I resolved that issue. Now another issue has come up.. The details page for the locations is displaying a black screen. Sometimes when I click on the screen a portion of the data will appear and I can see the information. It is similar to having weird artifact errors… maybe it is something with the webview?

        • Bob Sagget on August 4, 2013 at 9:41 am

          Ok to fix the black screen being displayed I had to remove LinearLayout from the .xml file and just leave the WebView. This fixed the issue.

    • xavi on August 9, 2013 at 8:21 pm

      Hi Bob,

      I have the same problem when I click on a location’s name. Do you remember how did you solved this?

      Thank you

  11. xavi on August 16, 2013 at 5:03 pm

    Hi George, thanks for your tutorials!

    I have a probem when I click on a location’s name: the app crashes and the logCat says that there’s a NullPointerException on PlaceDetailsActivity.ParserTask.onPostExecute, on the first line of this function.

    I’m not able to solve it, would you give me some advice?

    Thanks a lot

    Xavi

  12. akhwan on August 22, 2013 at 5:25 pm

    it is not work in indonesia -_- “

  13. babu s on September 6, 2013 at 8:53 pm

    hi,

    I want to only one map location type at a time..if i select school and then atm, it shows both.i want to show only atm.then what to do ?

  14. Abhay Sood on October 13, 2013 at 1:00 pm

    I have a probem when I click on a location’s name: the app crashes and the logCat says that there’s a NullPointerException on PlaceDetailsActivity.ParserTask.onPostExecute, on the first line of this function.

    I’m not able to solve it, would you give me some advice?

    Thanks a lot

  15. kandarp on November 13, 2013 at 1:04 am

    sir nice tutorail but i m total new , may be silly question but
    what is “YOUR_BROWSER_API_KEY_FOR_PLACES”
    and how can i get it ??

  16. marmik on November 13, 2013 at 10:21 pm

    Sir,
    My application crashes as soon as I run it on emulator or my phone. I can’t figure out the problem.
    Thanks…

  17. shefi on November 27, 2013 at 4:53 pm

    I getting this error pls help

    The Google Play services resources were not found. Check your project configuration to ensure that the resources are included.

  18. divna on December 2, 2013 at 10:43 am

    Hi George,

    I am getting the Google Play services resources were not found. Check your project configuration to ensure that the resources are included.

    Though i have included it in my project. Please help. Would really appreciate.

    Thanks

  19. Gambie on January 24, 2014 at 9:07 pm

    Can you tell me the difference between PlaceJSONParser.java and PlaceDetailsJSONParser.java please I am a bit confused…

  20. Aman on February 10, 2014 at 3:14 pm

    Hiii Sir

    I have used both keys from the apis console but app crashes on start in my phone but on emulator drop downs comes and also a prompt which shows to update Google play services after adding tag

  21. rimesh on April 17, 2014 at 3:46 pm

    I am getting map displayed and also getting my current location, but nothing happens when I press Find button. please help.

  22. prakash on April 25, 2014 at 10:56 pm

    hi,

    i have tried your code. Emulator has started..but when i tried to run the apps..it is showing error “Unfortunately LocationPlaceDetailsV@ has been stopped”.

    how to fix this error..pls let me know

    regards
    prakash

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