This tutorial is very helpful if you are building any application which deals with user locations. In this article i explained how to integrate Google Places and Maps in your android application.
About Google Places
Google Places API is a service provided by Google which returns information about your nearest places by considering the latitude, longitude and radius of area. You can add or remove a place from their places service too. Everything is done just by sending an HTTP request with required parameters. Check their official documentation for more information.
Prerequisite
In this tutorial i used lot of my previous tutorials. If you are new to any of the following concepts, i recommend you learn that particular topic just to make this tutorial easy.
> Android Working with Google Maps
> Android GPS, Location Manager Tutorial
> Android Detect Internet Connection Status
Obtaining Google API Key
In order to make requests to Google Places API you need to provide your API key along with the other parameters. You can get your API key by going to Google Places APIs console. The same key can be used for all other google services. Check the following video to know how to get a api key.
New Project / Downloading required libraries
Open your Eclipse IDE and create a new android project and fill all the required details. Also make sure that you have the updated ADT (Android Development Tool) and Eclipse to latest version.
1. Create a new project File ? New ? Android Application Project.
For this project i downloaded lot of external jar files and added to my project. These libraries are used to parse the Google API response.
Go to http://code.google.com/p/google-api-java-client/wiki/Setup and download google-api-client-android2. Extract the files and place them (Not every file) inside libs folder in your project. The following are required files you need to paste in your project.
1. google-api-client-1.10.3-beta.jar 2. google-api-client-android2-1.10.3-beta.jar (only for SDK >= 2.1) 3. google-oauth-client-1.10.3-beta.jar 4. google-http-client-1.10.3-beta.jar 5. google-http-client-android2-1.10.3-beta.jar (only for SDK >= 2.1) 6. google-http-client-android3-1.10.3-beta.jar (only for SDK >= 3.0) 7. gson-2.1.jar 8. guava-11.0.1.jar 9. jackson-core-asl-1.9.4.jar 10. jsr305-1.3.9.jar 11. protobuf-java-2.2.0.jar
3. As this application needs internet connection, we need to detect whether user has working internet connection or not. For this i am creating a new class called ConnectionDetector.java and pasted the following code.
Refer Android Detect Internet Connection Status to know more about using this class.
package com.androidhive.googleplacesandmaps; import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkInfo; public class ConnectionDetector { private Context _context; public ConnectionDetector(Context context){ this._context = context; } /** * Checking for all possible internet providers * **/ public boolean isConnectingToInternet(){ ConnectivityManager connectivity = (ConnectivityManager) _context.getSystemService(Context.CONNECTIVITY_SERVICE); if (connectivity != null) { NetworkInfo[] info = connectivity.getAllNetworkInfo(); if (info != null) for (int i = 0; i < info.length; i++) if (info[i].getState() == NetworkInfo.State.CONNECTED) { return true; } } return false; } }
4. Just to show messages in Alert Dialog i am creating a reusable alert class so that you don’t have to write the alert code in all the activities. Create a new class and name it as AlertDialogManager.java
package com.androidhive.googleplacesandmaps; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; public class AlertDialogManager { /** * Function to display simple Alert Dialog * @param context - application context * @param title - alert dialog title * @param message - alert message * @param status - success/failure (used to set icon) * - pass null if you don't want icon * */ public void showAlertDialog(Context context, String title, String message, Boolean status) { AlertDialog alertDialog = new AlertDialog.Builder(context).create(); // Setting Dialog Title alertDialog.setTitle(title); // Setting Dialog Message alertDialog.setMessage(message); if(status != null) // Setting alert dialog icon alertDialog.setIcon((status) ? R.drawable.success : R.drawable.fail); // Setting OK Button alertDialog.setButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { } }); // Showing Alert Message alertDialog.show(); } }
5. In this tutorial as everything is based on user’s current location, we need to get user’s current location using GPS. Create a new class called GPSTracker.java and paste the following code. To know more about this class usage follow this Android GPS, Location Manager Tutorial
package com.androidhive.googleplacesandmaps; import android.app.AlertDialog; import android.app.Service; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.os.IBinder; import android.provider.Settings; import android.util.Log; public class GPSTracker extends Service implements LocationListener { private final Context mContext; // flag for GPS status boolean isGPSEnabled = false; // flag for network status boolean isNetworkEnabled = false; // flag for GPS status boolean canGetLocation = false; Location location = null; // location double latitude; // latitude double longitude; // longitude // The minimum distance to change Updates in meters private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters // The minimum time between updates in milliseconds private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute // Declaring a Location Manager protected LocationManager locationManager; public GPSTracker(Context context) { this.mContext = context; getLocation(); } public Location getLocation() { try { locationManager = (LocationManager) mContext .getSystemService(LOCATION_SERVICE); // getting GPS status isGPSEnabled = locationManager .isProviderEnabled(LocationManager.GPS_PROVIDER); // getting network status isNetworkEnabled = locationManager .isProviderEnabled(LocationManager.NETWORK_PROVIDER); if (!isGPSEnabled && !isNetworkEnabled) { // no network provider is enabled } else { this.canGetLocation = true; if (isNetworkEnabled) { locationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this); Log.d("Network", "Network Enabled"); if (locationManager != null) { location = locationManager .getLastKnownLocation(LocationManager.NETWORK_PROVIDER); if (location != null) { latitude = location.getLatitude(); longitude = location.getLongitude(); } } } // if GPS Enabled get lat/long using GPS Services if (isGPSEnabled) { if (location == null) { locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this); Log.d("GPS", "GPS Enabled"); if (locationManager != null) { location = locationManager .getLastKnownLocation(LocationManager.GPS_PROVIDER); if (location != null) { latitude = location.getLatitude(); longitude = location.getLongitude(); } } } } } } catch (Exception e) { e.printStackTrace(); } return location; } /** * Stop using GPS listener Calling this function will stop using GPS in your * app * */ public void stopUsingGPS() { if (locationManager != null) { locationManager.removeUpdates(GPSTracker.this); } } /** * Function to get latitude * */ public double getLatitude() { if (location != null) { latitude = location.getLatitude(); } // return latitude return latitude; } /** * Function to get longitude * */ public double getLongitude() { if (location != null) { longitude = location.getLongitude(); } // return longitude return longitude; } /** * Function to check GPS/wifi enabled * * @return boolean * */ public boolean canGetLocation() { return this.canGetLocation; } /** * Function to show settings alert dialog On pressing Settings button will * lauch Settings Options * */ public void showSettingsAlert() { AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext); // Setting Dialog Title alertDialog.setTitle("GPS is settings"); // Setting Dialog Message alertDialog .setMessage("GPS is not enabled. Do you want to go to settings menu?"); // On pressing Settings button alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Intent intent = new Intent( Settings.ACTION_LOCATION_SOURCE_SETTINGS); mContext.startActivity(intent); } }); // on pressing cancel button alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }); // Showing Alert Message alertDialog.show(); } @Override public void onLocationChanged(Location location) { } @Override public void onProviderDisabled(String provider) { } @Override public void onProviderEnabled(String provider) { } @Override public void onStatusChanged(String provider, int status, Bundle extras) { } @Override public IBinder onBind(Intent arg0) { return null; } }
6. While parsing google places api response, it is better to make every place as an object to make it reusable component. So create the following classes.
Place.java – Single place as object
package com.androidhive.googleplacesandmaps; import java.io.Serializable; import com.google.api.client.util.Key; /** Implement this class from "Serializable" * So that you can pass this class Object to another using Intents * Otherwise you can't pass to another actitivy * */ public class Place implements Serializable { @Key public String id; @Key public String name; @Key public String reference; @Key public String icon; @Key public String vicinity; @Key public Geometry geometry; @Key public String formatted_address; @Key public String formatted_phone_number; @Override public String toString() { return name + " - " + id + " - " + reference; } public static class Geometry implements Serializable { @Key public Location location; } public static class Location implements Serializable { @Key public double lat; @Key public double lng; } }
PlacesList.java – List of places
package com.androidhive.googleplacesandmaps; import java.io.Serializable; import java.util.List; import com.google.api.client.util.Key; /** Implement this class from "Serializable" * So that you can pass this class Object to another using Intents * Otherwise you can't pass to another actitivy * */ public class PlacesList implements Serializable { @Key public String status; @Key public List<Place> results; }
PlaceDetails.java – Single place full details as object
package com.androidhive.googleplacesandmaps; import java.io.Serializable; import com.google.api.client.util.Key; /** Implement this class from "Serializable" * So that you can pass this class Object to another using Intents * Otherwise you can't pass to another actitivy * */ public class PlaceDetails implements Serializable { @Key public String status; @Key public Place result; @Override public String toString() { if (result!=null) { return result.toString(); } return super.toString(); } }
Getting Google Places
7. The actual part of getting google places is sarted now. Create a new class called GooglePlaces.java and write the following code. This class has function which are used to make request to Google Places API. While searching places your can search for particular type of places like cafe, restaurants etc,. Check list of supported types of places.
In the following class we have two functions
// This function is used to search your nearest places public PlacesList search(double latitude, double longitude, double radius, String types)...
// This function is used to get full details of a particular place public PlaceDetails getPlaceDetails(String reference)...
Final code
package com.androidhive.googleplacesandmaps; import org.apache.http.client.HttpResponseException; import android.util.Log; import com.google.api.client.googleapis.GoogleHeaders; import com.google.api.client.http.GenericUrl; import com.google.api.client.http.HttpRequest; import com.google.api.client.http.HttpRequestFactory; import com.google.api.client.http.HttpRequestInitializer; import com.google.api.client.http.HttpTransport; import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.http.json.JsonHttpParser; import com.google.api.client.json.jackson.JacksonFactory; @SuppressWarnings("deprecation") public class GooglePlaces { /** Global instance of the HTTP transport. */ private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); // Google API Key private static final String API_KEY = "AIzaSyCRLa4LQZWNQBcjCYcIVYA45i9i8zfClqc"; // Google Places serach url's private static final String PLACES_SEARCH_URL = "https://maps.googleapis.com/maps/api/place/search/json?"; private static final String PLACES_TEXT_SEARCH_URL = "https://maps.googleapis.com/maps/api/place/search/json?"; private static final String PLACES_DETAILS_URL = "https://maps.googleapis.com/maps/api/place/details/json?"; private double _latitude; private double _longitude; private double _radius; /** * Searching places * @param latitude - latitude of place * @params longitude - longitude of place * @param radius - radius of searchable area * @param types - type of place to search * @return list of places * */ public PlacesList search(double latitude, double longitude, double radius, String types) throws Exception { this._latitude = latitude; this._longitude = longitude; this._radius = radius; try { HttpRequestFactory httpRequestFactory = createRequestFactory(HTTP_TRANSPORT); HttpRequest request = httpRequestFactory .buildGetRequest(new GenericUrl(PLACES_SEARCH_URL)); request.getUrl().put("key", API_KEY); request.getUrl().put("location", _latitude + "," + _longitude); request.getUrl().put("radius", _radius); // in meters request.getUrl().put("sensor", "false"); if(types != null) request.getUrl().put("types", types); PlacesList list = request.execute().parseAs(PlacesList.class); // Check log cat for places response status Log.d("Places Status", "" + list.status); return list; } catch (HttpResponseException e) { Log.e("Error:", e.getMessage()); return null; } } /** * Searching single place full details * @param refrence - reference id of place * - which you will get in search api request * */ public PlaceDetails getPlaceDetails(String reference) throws Exception { try { HttpRequestFactory httpRequestFactory = createRequestFactory(HTTP_TRANSPORT); HttpRequest request = httpRequestFactory .buildGetRequest(new GenericUrl(PLACES_DETAILS_URL)); request.getUrl().put("key", API_KEY); request.getUrl().put("reference", reference); request.getUrl().put("sensor", "false"); PlaceDetails place = request.execute().parseAs(PlaceDetails.class); return place; } catch (HttpResponseException e) { Log.e("Error in Perform Details", e.getMessage()); throw e; } } /** * Creating http request Factory * */ public static HttpRequestFactory createRequestFactory( final HttpTransport transport) { return transport.createRequestFactory(new HttpRequestInitializer() { public void initialize(HttpRequest request) { GoogleHeaders headers = new GoogleHeaders(); headers.setApplicationName("AndroidHive-Places-Test"); request.setHeaders(headers); JsonHttpParser parser = new JsonHttpParser(new JacksonFactory()); request.addParser(parser); } }); } }
Showing Places in ListView
8. Create two xml files under layout folder required for creating a listview. In the following i am creating a listview and a button above the listview. Another file is for list item. Name the two files as activity_main.xml and list_item.xml
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <!-- Show on Map button --> <Button android:id="@+id/btn_show_map" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Show Places on Map" android:layout_alignParentTop="true" android:layout_marginTop="10dip"/> <!-- List view --> <ListView android:id="@+id/list" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_below="@id/btn_show_map"/> </RelativeLayout>
list_item.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" > <TextView android:id="@+id/reference" android:visibility="gone" android:layout_width="fill_parent" android:layout_height="wrap_content"/> <TextView android:id="@+id/name" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="10dip" android:textStyle="bold" android:textSize="16dip"/> </LinearLayout>
9. Open your main acitivity (my main activity name is MainActivity.java) and add following required variables.
public class MainActivity extends Activity { // flag for Internet connection status Boolean isInternetPresent = false; // Connection detector class ConnectionDetector cd; // Alert Dialog Manager AlertDialogManager alert = new AlertDialogManager(); // Google Places GooglePlaces googlePlaces; // Places List PlacesList nearPlaces; // GPS Location GPSTracker gps; // Button Button btnShowOnMap; // Progress dialog ProgressDialog pDialog; // Places Listview ListView lv; // ListItems data ArrayList<HashMap<String, String>> placesListItems = new ArrayList<HashMap<String,String>>(); // KEY Strings public static String KEY_REFERENCE = "reference"; // id of the place public static String KEY_NAME = "name"; // name of the place public static String KEY_VICINITY = "vicinity"; // Place area name @Override public void onCreate(Bundle savedInstanceState) {
In the following code
> First i am checking if user has internet connection or not. If not an alert is shown to user asking to connect to internet
> Second i am checking if user’s current location can be retrieved by GPS Location Manger. If not an alert is shown asking user to turn on GPS or Wifi.
> Third if user has both internet and GPS turned on an Async task is called to get Google places using new LoadPlaces().execute()
> In LoadPlaces() method once getting places is done all the data is attached in a ListView.
> Above the listview a button is placed which launches another activity to show all places on map.
package com.androidhive.googleplacesandmaps; import java.util.ArrayList; import java.util.HashMap; import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.text.Html; import android.util.Log; import android.view.Menu; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.Button; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.TextView; public class MainActivity extends Activity { // flag for Internet connection status Boolean isInternetPresent = false; // Connection detector class ConnectionDetector cd; // Alert Dialog Manager AlertDialogManager alert = new AlertDialogManager(); // Google Places GooglePlaces googlePlaces; // Places List PlacesList nearPlaces; // GPS Location GPSTracker gps; // Button Button btnShowOnMap; // Progress dialog ProgressDialog pDialog; // Places Listview ListView lv; // ListItems data ArrayList<HashMap<String, String>> placesListItems = new ArrayList<HashMap<String,String>>(); // KEY Strings public static String KEY_REFERENCE = "reference"; // id of the place public static String KEY_NAME = "name"; // name of the place public static String KEY_VICINITY = "vicinity"; // Place area name @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); cd = new ConnectionDetector(getApplicationContext()); // Check if Internet present isInternetPresent = cd.isConnectingToInternet(); if (!isInternetPresent) { // Internet Connection is not present alert.showAlertDialog(MainActivity.this, "Internet Connection Error", "Please connect to working Internet connection", false); // stop executing code by return return; } // creating GPS Class object gps = new GPSTracker(this); // check if GPS location can get if (gps.canGetLocation()) { Log.d("Your Location", "latitude:" + gps.getLatitude() + ", longitude: " + gps.getLongitude()); } else { // Can't get user's current location alert.showAlertDialog(MainActivity.this, "GPS Status", "Couldn't get location information. Please enable GPS", false); // stop executing code by return return; } // Getting listview lv = (ListView) findViewById(R.id.list); // button show on map btnShowOnMap = (Button) findViewById(R.id.btn_show_map); // calling background Async task to load Google Places // After getting places from Google all the data is shown in listview new LoadPlaces().execute(); /** Button click event for shown on map */ btnShowOnMap.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { Intent i = new Intent(getApplicationContext(), PlacesMapActivity.class); // Sending user current geo location i.putExtra("user_latitude", Double.toString(gps.getLatitude())); i.putExtra("user_longitude", Double.toString(gps.getLongitude())); // passing near places to map activity i.putExtra("near_places", nearPlaces); // staring activity startActivity(i); } }); /** * ListItem click event * On selecting a listitem SinglePlaceActivity is launched * */ lv.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // getting values from selected ListItem String reference = ((TextView) view.findViewById(R.id.reference)).getText().toString(); // Starting new intent Intent in = new Intent(getApplicationContext(), SinglePlaceActivity.class); // Sending place refrence id to single place activity // place refrence id used to get "Place full details" in.putExtra(KEY_REFERENCE, reference); startActivity(in); } }); } /** * Background Async Task to Load Google places * */ class LoadPlaces extends AsyncTask<String, String, String> { /** * Before starting background thread Show Progress Dialog * */ @Override protected void onPreExecute() { super.onPreExecute(); pDialog = new ProgressDialog(MainActivity.this); pDialog.setMessage(Html.fromHtml("<b>Search</b><br/>Loading Places...")); pDialog.setIndeterminate(false); pDialog.setCancelable(false); pDialog.show(); } /** * getting Places JSON * */ protected String doInBackground(String... args) { // creating Places class object googlePlaces = new GooglePlaces(); try { // Separeate your place types by PIPE symbol "|" // If you want all types places make it as null // Check list of types supported by google // String types = "cafe|restaurant"; // Listing places only cafes, restaurants // Radius in meters - increase this value if you don't find any places double radius = 1000; // 1000 meters // get nearest places nearPlaces = googlePlaces.search(gps.getLatitude(), gps.getLongitude(), radius, types); } catch (Exception e) { e.printStackTrace(); } return null; } /** * After completing background task Dismiss the progress dialog * and show the data in UI * Always use runOnUiThread(new Runnable()) to update UI from background * thread, otherwise you will get error * **/ protected void onPostExecute(String file_url) { // dismiss the dialog after getting all products pDialog.dismiss(); // updating UI from Background Thread runOnUiThread(new Runnable() { public void run() { /** * Updating parsed Places into LISTVIEW * */ // Get json response status String status = nearPlaces.status; // Check for all possible status if(status.equals("OK")){ // Successfully got places details if (nearPlaces.results != null) { // loop through each place for (Place p : nearPlaces.results) { HashMap<String, String> map = new HashMap<String, String>(); // Place reference won't display in listview - it will be hidden // Place reference is used to get "place full details" map.put(KEY_REFERENCE, p.reference); // Place name map.put(KEY_NAME, p.name); // adding HashMap to ArrayList placesListItems.add(map); } // list adapter ListAdapter adapter = new SimpleAdapter(MainActivity.this, placesListItems, R.layout.list_item, new String[] { KEY_REFERENCE, KEY_NAME}, new int[] { R.id.reference, R.id.name }); // Adding data into listview lv.setAdapter(adapter); } } else if(status.equals("ZERO_RESULTS")){ // Zero results found alert.showAlertDialog(MainActivity.this, "Near Places", "Sorry no places found. Try to change the types of places", false); } else if(status.equals("UNKNOWN_ERROR")) { alert.showAlertDialog(MainActivity.this, "Places Error", "Sorry unknown error occured.", false); } else if(status.equals("OVER_QUERY_LIMIT")) { alert.showAlertDialog(MainActivity.this, "Places Error", "Sorry query limit to google places is reached", false); } else if(status.equals("REQUEST_DENIED")) { alert.showAlertDialog(MainActivity.this, "Places Error", "Sorry error occured. Request is denied", false); } else if(status.equals("INVALID_REQUEST")) { alert.showAlertDialog(MainActivity.this, "Places Error", "Sorry error occured. Invalid Request", false); } else { alert.showAlertDialog(MainActivity.this, "Places Error", "Sorry error occured.", false); } } }); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }


Getting single place full details
11. If you see the api json response from google, each place has a unique reference id which is used to get place complete details.
In your project create a new Activity class and name it as SinglePlaceActivity.java and respected layout file and name it as single_place.xml
single_place.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" android:padding="10dip"> <!-- Name Label --> <TextView android:text="Name:" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="10dip" android:layout_marginBottom="5dip" android:textStyle="bold"/> <!-- Name Value --> <TextView android:id="@+id/name" android:layout_width="fill_parent" android:layout_height="wrap_content"/> <!-- Address Label --> <TextView android:text="Address:" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="15dip" android:layout_marginBottom="5dip" android:textStyle="bold"/> <!-- Address Value --> <TextView android:id="@+id/address" android:layout_width="fill_parent" android:layout_height="wrap_content"/> <!-- Phone Number Label --> <TextView android:id="@+id/phone" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="10dip"/> <!-- Location Value --> <TextView android:id="@+id/location" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="15dip" android:layout_marginBottom="5dip"/> </LinearLayout>
And below is the code for SinglePlaceActivity.java class. In the following code
> First the place reference id is received from MainActivity.java activity
> Second using the place reference id a background Async thread LoadSinglePlaceDetails() is called to get full details of a place
package com.androidhive.googleplacesandmaps; import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.text.Html; import android.util.Log; import android.widget.TextView; public class SinglePlaceActivity extends Activity { // flag for Internet connection status Boolean isInternetPresent = false; // Connection detector class ConnectionDetector cd; // Alert Dialog Manager AlertDialogManager alert = new AlertDialogManager(); // Google Places GooglePlaces googlePlaces; // Place Details PlaceDetails placeDetails; // Progress dialog ProgressDialog pDialog; // KEY Strings public static String KEY_REFERENCE = "reference"; // id of the place @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.single_place); Intent i = getIntent(); // Place referece id String reference = i.getStringExtra(KEY_REFERENCE); // Calling a Async Background thread new LoadSinglePlaceDetails().execute(reference); } /** * Background Async Task to Load Google places * */ class LoadSinglePlaceDetails extends AsyncTask<String, String, String> { /** * Before starting background thread Show Progress Dialog * */ @Override protected void onPreExecute() { super.onPreExecute(); pDialog = new ProgressDialog(SinglePlaceActivity.this); pDialog.setMessage("Loading profile ..."); pDialog.setIndeterminate(false); pDialog.setCancelable(false); pDialog.show(); } /** * getting Profile JSON * */ protected String doInBackground(String... args) { String reference = args[0]; // creating Places class object googlePlaces = new GooglePlaces(); // Check if used is connected to Internet try { placeDetails = googlePlaces.getPlaceDetails(reference); } catch (Exception e) { e.printStackTrace(); } return null; } /** * After completing background task Dismiss the progress dialog * **/ protected void onPostExecute(String file_url) { // dismiss the dialog after getting all products pDialog.dismiss(); // updating UI from Background Thread runOnUiThread(new Runnable() { public void run() { /** * Updating parsed Places into LISTVIEW * */ if(placeDetails != null){ String status = placeDetails.status; // check place deatils status // Check for all possible status if(status.equals("OK")){ if (placeDetails.result != null) { String name = placeDetails.result.name; String address = placeDetails.result.formatted_address; String phone = placeDetails.result.formatted_phone_number; String latitude = Double.toString(placeDetails.result.geometry.location.lat); String longitude = Double.toString(placeDetails.result.geometry.location.lng); Log.d("Place ", name + address + phone + latitude + longitude); // Displaying all the details in the view // single_place.xml TextView lbl_name = (TextView) findViewById(R.id.name); TextView lbl_address = (TextView) findViewById(R.id.address); TextView lbl_phone = (TextView) findViewById(R.id.phone); TextView lbl_location = (TextView) findViewById(R.id.location); // Check for null data from google // Sometimes place details might missing name = name == null ? "Not present" : name; // if name is null display as "Not present" address = address == null ? "Not present" : address; phone = phone == null ? "Not present" : phone; latitude = latitude == null ? "Not present" : latitude; longitude = longitude == null ? "Not present" : longitude; lbl_name.setText(name); lbl_address.setText(address); lbl_phone.setText(Html.fromHtml("<b>Phone:</b> " + phone)); lbl_location.setText(Html.fromHtml("<b>Latitude:</b> " + latitude + ", <b>Longitude:</b> " + longitude)); } } else if(status.equals("ZERO_RESULTS")){ alert.showAlertDialog(SinglePlaceActivity.this, "Near Places", "Sorry no place found.", false); } else if(status.equals("UNKNOWN_ERROR")) { alert.showAlertDialog(SinglePlaceActivity.this, "Places Error", "Sorry unknown error occured.", false); } else if(status.equals("OVER_QUERY_LIMIT")) { alert.showAlertDialog(SinglePlaceActivity.this, "Places Error", "Sorry query limit to google places is reached", false); } else if(status.equals("REQUEST_DENIED")) { alert.showAlertDialog(SinglePlaceActivity.this, "Places Error", "Sorry error occured. Request is denied", false); } else if(status.equals("INVALID_REQUEST")) { alert.showAlertDialog(SinglePlaceActivity.this, "Places Error", "Sorry error occured. Invalid Request", false); } else { alert.showAlertDialog(SinglePlaceActivity.this, "Places Error", "Sorry error occured.", false); } }else{ alert.showAlertDialog(SinglePlaceActivity.this, "Places Error", "Sorry error occured.", false); } } }); } } }

Showing all the places on the Map
If you haven’t worked with maps yet, go through Android Working with Google Maps to get an idea about implementing google maps in your android application.
In our MainActivity you can find a button called Show On Map to show all the places on the map. This the code to call map activity by passing all the places information to PlacesMapActivity.java
This code is implemented in MainActivity.java class
/** Button click event for shown on map */ btnShowOnMap.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { Intent i = new Intent(getApplicationContext(), PlacesMapActivity.class); // Sending user current geo location i.putExtra("user_latitude", Double.toString(gps.getLatitude())); i.putExtra("user_longitude", Double.toString(gps.getLongitude())); // passing near places to map activity i.putExtra("near_places", nearPlaces); // staring activity startActivity(i); } });
12. Create a new class called AddItemizedOverlay.java which is helper class for map activity used to display markers, geopoints on a map.
package com.androidhive.googleplacesandmaps; import java.util.ArrayList; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.graphics.drawable.Drawable; import android.view.MotionEvent; import com.google.android.maps.GeoPoint; import com.google.android.maps.ItemizedOverlay; import com.google.android.maps.MapView; import com.google.android.maps.OverlayItem; /** * Class used to place marker or any overlay items on Map * */ public class AddItemizedOverlay extends ItemizedOverlay<OverlayItem> { private ArrayList<OverlayItem> mapOverlays = new ArrayList<OverlayItem>(); private Context context; public AddItemizedOverlay(Drawable defaultMarker) { super(boundCenterBottom(defaultMarker)); } public AddItemizedOverlay(Drawable defaultMarker, Context context) { this(defaultMarker); this.context = context; } @Override public boolean onTouchEvent(MotionEvent event, MapView mapView) { if (event.getAction() == 1) { GeoPoint geopoint = mapView.getProjection().fromPixels( (int) event.getX(), (int) event.getY()); // latitude double lat = geopoint.getLatitudeE6() / 1E6; // longitude double lon = geopoint.getLongitudeE6() / 1E6; //Toast.makeText(context, "Lat: " + lat + ", Lon: "+lon, Toast.LENGTH_SHORT).show(); } return false; } @Override protected OverlayItem createItem(int i) { return mapOverlays.get(i); } @Override public int size() { return mapOverlays.size(); } @Override protected boolean onTap(int index) { OverlayItem item = mapOverlays.get(index); AlertDialog.Builder dialog = new AlertDialog.Builder(this.context); dialog.setTitle(item.getTitle()); dialog.setMessage(item.getSnippet()); dialog.setPositiveButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { } }); dialog.show(); return true; } public void addOverlay(OverlayItem overlay) { mapOverlays.add(overlay); } public void populateNow(){ this.populate(); } }
13. Create a new class called PlacesMapActivity.java which is the activity to display all the places on the map.
In the following code
> User current location is showed on map in a red marker.
> Remaining all the places are shown in blue markers.
package com.androidhive.googleplacesandmaps; import java.util.List; import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.util.Log; import com.google.android.maps.GeoPoint; import com.google.android.maps.MapActivity; import com.google.android.maps.MapController; import com.google.android.maps.MapView; import com.google.android.maps.Overlay; import com.google.android.maps.OverlayItem; public class PlacesMapActivity extends MapActivity { // Nearest places PlacesList nearPlaces; // Map view MapView mapView; // Map overlay items List<Overlay> mapOverlays; AddItemizedOverlay itemizedOverlay; GeoPoint geoPoint; // Map controllers MapController mc; double latitude; double longitude; OverlayItem overlayitem; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.map_places); // Getting intent data Intent i = getIntent(); // Users current geo location String user_latitude = i.getStringExtra("user_latitude"); String user_longitude = i.getStringExtra("user_longitude"); // Nearplaces list nearPlaces = (PlacesList) i.getSerializableExtra("near_places"); mapView = (MapView) findViewById(R.id.mapView); mapView.setBuiltInZoomControls(true); mapOverlays = mapView.getOverlays(); // Geopoint to place on map geoPoint = new GeoPoint((int) (Double.parseDouble(user_latitude) * 1E6), (int) (Double.parseDouble(user_longitude) * 1E6)); // Drawable marker icon Drawable drawable_user = this.getResources() .getDrawable(R.drawable.mark_red); itemizedOverlay = new AddItemizedOverlay(drawable_user, this); // Map overlay item overlayitem = new OverlayItem(geoPoint, "Your Location", "That is you!"); itemizedOverlay.addOverlay(overlayitem); mapOverlays.add(itemizedOverlay); itemizedOverlay.populateNow(); // Drawable marker icon Drawable drawable = this.getResources() .getDrawable(R.drawable.mark_blue); itemizedOverlay = new AddItemizedOverlay(drawable, this); mc = mapView.getController(); // These values are used to get map boundary area // The area where you can see all the markers on screen int minLat = Integer.MAX_VALUE; int minLong = Integer.MAX_VALUE; int maxLat = Integer.MIN_VALUE; int maxLong = Integer.MIN_VALUE; // check for null in case it is null if (nearPlaces.results != null) { // loop through all the places for (Place place : nearPlaces.results) { latitude = place.geometry.location.lat; // latitude longitude = place.geometry.location.lng; // longitude // Geopoint to place on map geoPoint = new GeoPoint((int) (latitude * 1E6), (int) (longitude * 1E6)); // Map overlay item overlayitem = new OverlayItem(geoPoint, place.name, place.vicinity); itemizedOverlay.addOverlay(overlayitem); // calculating map boundary area minLat = (int) Math.min( geoPoint.getLatitudeE6(), minLat ); minLong = (int) Math.min( geoPoint.getLongitudeE6(), minLong); maxLat = (int) Math.max( geoPoint.getLatitudeE6(), maxLat ); maxLong = (int) Math.max( geoPoint.getLongitudeE6(), maxLong ); } mapOverlays.add(itemizedOverlay); // showing all overlay items itemizedOverlay.populateNow(); } // Adjusting the zoom level so that you can see all the markers on map mapView.getController().zoomToSpan(Math.abs( minLat - maxLat ), Math.abs( minLong - maxLong )); // Showing the center of the map mc.animateTo(new GeoPoint((maxLat + minLat)/2, (maxLong + minLong)/2 )); mapView.postInvalidate(); } @Override protected boolean isRouteDisplayed() { return false; } }


Finally if you downloaded the code provided in this tutorial, don’t forget to replace the Google API key with your own key.