Monday, May 23, 2011

Introducing the Google Places API

A couple of weeks ago, at the Google I/O developer conference in San Francisco, Google announced the opening up and general availability of the Google Places API. The Google Places API is an API that returns information about Places. It is part of the Google Maps API Web Services, a collection of HTTP interfaces to Google services providing geographic data for your maps applications. The goal of this article is to go over the API by using a sample application that actually does these API calls. We'll cover each API request in detail, look at the raw JSON response coming back from the Google Places API, see how to process the response using the Google APIs Client Library for Java. We'll also convert the JSON response into a java based model, and use that model to display the results.





The API covers :
  • establishments
  • geographic locations
  • prominent points of interest
As most Google APIs, interaction is done using HTTP requests. Applications wishing to access the API will need to have an API key (see google console).

Authentication and authorization

An important thing to note is that the Google Places API doesn't require any user authentication. Typically, when interacting with Google APIs, the end-user needs to authenticate in order to authorize access.
For example, in order to use the Google Buzz API to post messages, users needs to authorize the application to post messages on their behalf.
Google supports a number of different ways of performing authentication / authorization,
depending on the API that is being used.

The Google Places API is a different story. Although you also need to authenticate before being able to use the API, the authentication is done on an application level, based on an API key. After the developer uses the Google API Console to register a project (application), he can retrieve an API key that he needs to use when interacting with the Places API.

As such, there is no direct link between the user and the Places API. The application is responsible for making the call, and as far as the user is concerned, all calls are anonynomous as he doesn't need to provide a password, or authorize any kind of access.

Google Places API Requests

The Google Places API supports 4 basic Place requests :
  • Place Searches :
    return a list of nearby Places based on a user's location.
  • Place Details :
    requests return more detailed information about a specific Place.
  • Place Check-ins :
    allow the application to report that a user has checked in to a Place.
  • Place Reports :
    allows the application to add / delete Places to the Place service

Note : Check-ins have an effect on the place's ranking in your application's Place Search results, and should not be confused with Google Latitude check-ins.

Google Places Autocomplete API

An additional API, called the Google Places Autocomplete API, can be considered an add-on to the Google Places API. Its a web service that returns Place information based on text search terms, and, optionally, geographic bounds within which to search

We'll cover the Places Searches / Places Details and the Autocomplete API in this article.

Prerequisites

The first thing you'll need to do before interacting with the API is to get yourself an API key. This is done by going to the Google API console and retrieving your API Key. Each Google account can login the console, and define different projects (applications). Each project / application gets its own API Key.

The API key is a required field when interacting with the Google Places API, and needs to be sent with each request. It's used to identify your application,
required to maintain rankings, performing checkins on an application level.

The next thing you'll need is to get familiar with the different API calls supported by the google places API.

Google Places API - Places Search

Searching for places is done through the https://maps.googleapis.com/maps/api/place/search endpoint.

We need to provide the following parameters:

NameDescription
locationThe latitude/longitude around which to retrieve Place information. This must be provided as a google.maps.LatLng object. This means that we provide a latitude and a longitude value, seperated by a comma (ex: -31.203405,125.244141)
radiusThe distance (in meters) within which to return Place results. The recommended best practice is to set radius based on the accuracy of the location signal as given by the location sensor. Note that setting a radius biases results to the indicated area, but may not fully restrict results to the specified area.
sensorndicates whether or not the Place request came from a device using a location sensor (e.g. a GPS) to determine the location sent in this request. This value must be either true or false.

The code to execute the search looks like this:

private static final String PLACES_SEARCH_URL =  "https://maps.googleapis.com/maps/api/place/search/json?";
 
private static final boolean PRINT_AS_STRING = false;


 public void performSearch() throws Exception {
  try {
   System.out.println("Perform Search ....");
   System.out.println("-------------------");
   HttpRequestFactory httpRequestFactory = createRequestFactory(transport);
   HttpRequest request = httpRequestFactory.buildGetRequest(new GenericUrl(PLACES_SEARCH_URL));
   request.url.put("key", API_KEY);
   request.url.put("location", latitude + "," + longitude);
   request.url.put("radius", 500);
   request.url.put("sensor", "false");
   
   if (PRINT_AS_STRING) {
    System.out.println(request.execute().parseAsString());
   } else {
    
    PlacesList places = request.execute().parseAs(PlacesList.class);
    System.out.println("STATUS = " + places.status);
    for (Place place : places.results) {
     System.out.println(place);
    }
   }

  } catch (HttpResponseException e) {
   System.err.println(e.response.parseAsString());
   throw e;
  }
 }


The API responds with the following JSON string that gets converted into a java based model by the Google APIs Client Library for Java. As you can see it contains a lot of information related to a place, including a reference (that I replaced here to make the code sample more clear). The reference included in this response will be used to retrieve the place details (see later on).

{
"status": "OK",
"results": [ {
"name": "Downtown",
"vicinity": "San Francisco",
"types": [ "neighborhood", "political" ],
"geometry": {
"location": {
"lat": 37.7869343,
"lng": -122.4099154
},
"viewport": {
"southwest": {
"lat": 37.7781157,
"lng": -122.4259228
},
"northeast": {
"lat": 37.7957519,
"lng": -122.3939080
}
}
},
"icon": "http://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png",
"reference": "someRef",
"id": "b7fa5ebba26a10513d18e1fd50628f082ffbd1a2"
}, {
"name": "San Francisco Marriott Marquis",
"vicinity": "Fourth Street, San Francisco",
"types": [ "lodging", "establishment" ],
"geometry": {
"location": {
"lat": 37.7836320,
"lng": -122.3998260
}
},
"icon": "http://maps.gstatic.com/mapfiles/place_api/icons/lodging-71.png",
"reference": "someRef",
"id": "f007d2f91c0070ebdfec60275baa33623f0b771b"
}, {
"name": "Yerba Buena Center for the Arts (YBCA)",
"vicinity": "Mission Street, San Francisco",
"types": [ "establishment" ],
"geometry": {
"location": {
"lat": 37.7861120,
"lng": -122.4020270
}
},
"icon": "http://maps.gstatic.com/mapfiles/place_api/icons/generic_business-71.png",
"reference": "someRef",
"id": "ed6f8fefe44e17ead83bf08f5eb07f8dfe99db93"
} ],
"html_attributions": [ ]
}
The sample application will output the following, based on our java based model :
Perform Search ....
-------------------
STATUS = OK
Downtown - b7fa5ebba26a10513d18e1fd50628f082ffbd1a2 - CnRpAAAAeeH91oALhbaI6kgfTP9nfwfFGMhn2NSE_qZQXgk-xC1SimPdw3IevDHlykZ4RKT0O75Gpq2pVnWerUaj9eM2MLPfGhp7scVt78Whl95o_HUTczWggtu-CuwNPNmZTBxgX4o56J-zb4iOLX5A16d00BIQQ8Vf5NYhxzIr3HXIX_DZeRoU1sqwOFEFS5PVKze64-cZbIYosm4
San Francisco Marriott Marquis - f007d2f91c0070ebdfec60275baa33623f0b771b - CoQBdgAAAGg0ekN4sk4cwwipeMUOycf1sJunhbR92OMnZSFY5BqbRyJLwsPtKeCU8pTe-ZLC91h6ldnkAiOTJlioBk7kS-UwDkVvDi5Iq8OjGXiX4m3xL5nmw73S04L9gFmZBTDfhRzVY6pAM337S0XF6WEPqgzPLf71cW3N1Qsjr0a9U-A8EhCfVuJuZJQbdmzGFLtzu5K2GhTVrea_ZS0mdM3QDnPkUAsgU8ry4g
Yerba Buena Center for the Arts (YBCA) - ed6f8fefe44e17ead83bf08f5eb07f8dfe99db93 - CoQBfQAAADtDN0tqr5s5VC6P096Dg7UFjBEI9l8HIOYwQTfV_0yX9G9pyP6OHu8gNOmE_cm-wmipdV1mpuxh4wyYUh0jT2Etbwi-3GjCIAs6d0bjMDrJ84c2Lumy6k17yMn7CcITUGCfIzAyMBZRIIV41PxvFT74DfLJiBw2N3JS6gYVg6jvEhC3CUEuSONQ9G9lf1u-IV2jGhSXvuMFNV9vwzZZPkMhevbUzknkQw
Contemporary Jewish Museum - 350068fffb5f1ac6ffc28a7a54e503f2c578a881 - CoQBcgAAAI20uthq2U3BV576TrBL6iuUJTxsiuLD4UhmJ_VZYB34nMAey2K8W9G_Kkv3EimU_01U3O3blFO2iqRsZGNKf_3tDTYp3dZzkLTcuxvA3FB7v7MlYF8c31UjeRkETTBqlI20XbLqfyHivaIg1XNxMli9n7wVfHn6R7VtVmTXjyRYEhBDc5y7UkwcLh30W7tUVHESGhRf0CHLzW2Zc3fQgb3NaqXBdsMv8A
The W San Francisco Hotel - 2bee7ad63a1626e7193c338e6cce68b3c362236a - CnRwAAAAf4JVWflXis5mdzCgL7S98dIbvZmhrUxfM3o-hyLFZ-yZ4atKUyEPTdxIH6TaTZJE1aHv7nBfGPrvA4Tts7mOkd1aZX-jF1QbFsbracKYFsH51tTeQP9rNFJ2QVrhXypmk2uMWDmbt1n0te302P1HDRIQseiXd5zdOpMFWPaz9TWm_xoUP4mzmfNZTRTIb2oTNFr0sFlwuuc
InterContinental Hotel - fbbcc1bcbf1916a9743f8f85cb98e561ae75c701 - CnRuAAAAE2NiBZYsVcFtSmW9BpplomEXbHUl5aiKlKlZGPRKWvhrUW2ReejnL2Hvq2SEj8JoFOg2znwYbbc9WVeomYDWPfFPNDONy9HDzjBg7yk-wRE97ggSi4-nUwdvgGW5knuhcLq7tmGl5wNlTpaKkQYTlhIQ4b_l0hju6fDzp2r4Gt1ShxoUL75dky-4Yo0JJxyUUEc4_kbMddQ
Moscone Center - abbda52af18357b0575838ff00c7dd6ed69ed866 - CnRmAAAAWh19fWBAb6xH2JcJqvndlIm_4YmKCrDoIfm7He0q8ONzs6Ku-RIDQUTGRm8VdrcV6sHUGYK5LTq6GfHpwFbgGzMJvDVP5Xu-qhcQN27cUf7emjBiuZD0kF6CLRag1m6QDZyHwjGNjOTL-CvyBVbj3BIQH35mtZMTkBwecCQaSPDPERoUJW7Nqo7EmmLikLA_7IL7Pf838ZQ

Where the request.execute().parseAsString() returns the response coming from the API as raw text, you can see that in this example I've used the request.execute().parseAs(PlacesList.class) to have the response converted into a java based model that's easier to work with. It takes away the plumbing of having to parse the JSON string, and converting it into a model ourselves. It's one of the many interesting features of the Google APIs Client Library for Java. You simply provide a reference to a java class that has certain fields annotated with the @Key attribute. The client library will simply convert the JSON keys into the java model, by mapping those JSON keys with the fields in your class.

A simple representation of a list of places looks like this :

package com.ecs.googleplaces.sample;

import java.util.List;

import com.google.api.client.util.Key;

public class PlacesList {

 @Key
 public String status;

 @Key
 public List results;

}

The actual Place object looks like this :
package com.ecs.googleplaces.sample;

import com.google.api.client.util.Key;

public class Place {

 @Key
 public String id;
 
 @Key
 public String name;
 
 @Key
 public String reference;

 @Override
 public String toString() {
  return name + " - " + id + " - " + reference;
 }
 
}
I highly recommend you looking into the Google APIs Client Library for Java, as it's the preferred way of accessing Google APIs on a variety of platforms (including Android). In fact, it also allows you to call pretty much any REST based API.

Another thing I would like to highlight here is the HttpRequestFactory httpRequestFactory = createRequestFactory(transport); method. Also part of the Google APIs Client Library for Java, it offers us a factory to create HTTP GET or POST requests. The method is implemented like this :


private static final HttpTransport transport = new ApacheHttpTransport();

public static HttpRequestFactory createRequestFactory(final HttpTransport transport) {

return transport.createRequestFactory(new HttpRequestInitializer() {
public void initialize(HttpRequest request) {
GoogleHeaders headers = new GoogleHeaders();
headers.setApplicationName("Google-Places-DemoApp");
request.headers=headers;
JsonHttpParser parser = new JsonHttpParser();
parser.jsonFactory = new JacksonFactory();
request.addParser(parser);
}
});
}

As you can seem it sets up a factory based on an HTTP transport. It sets an applicationName on the HTTP headers, and attaches a JSON parser to the HttpRequest. When using Google APIs that cannot be accessed unauthorized, here is where you would setup security mechanisms like OAuth or ClientLogin. As you don't need to be authenticated to use the Places API, the transport doesn't need to be secured.

Google Places API - Places Detail

Details of a certain place can also be fetched. For this API call we'll be using the https://maps.googleapis.com/maps/api/place/details endpoint. In order to retrieve the details of a place, we need to provide the following parameters :

NameDescription
referenceA textual identifier that uniquely identifies a place, returned from a Place search request.
sensorndicates whether or not the Place request came from a device using a location sensor (e.g. a GPS) to determine the location sent in this request. This value must be either true or false.

The actual code to perform the API call looks like this :

public void performDetails(String reference) throws Exception {
  try {
   System.out.println("Perform Place Detail....");
   System.out.println("-------------------");
   HttpRequestFactory httpRequestFactory = createRequestFactory(transport);
   HttpRequest request = httpRequestFactory.buildGetRequest(new GenericUrl(PLACES_DETAILS_URL));
   request.url.put("key", API_KEY);
   request.url.put("reference", reference);
   request.url.put("sensor", "false");
   
   if (PRINT_AS_STRING) {
    System.out.println(request.execute().parseAsString());
   } else {
    PlaceDetail place = request.execute().parseAs(PlaceDetail.class);
    System.out.println(place);
   }

  } catch (HttpResponseException e) {
   System.err.println(e.response.parseAsString());
   throw e;
  }
 }

{
"status": "OK",
"result": {
"name": "Moscone Center",
"vicinity": "Howard St, San Francisco",
"types": [ "local_government_office", "establishment" ],
"formatted_phone_number": "(415) 974-4000",
"formatted_address": "747 Howard St, San Francisco, California 94103, United States",
"address_components": [ {
"long_name": "747",
"short_name": "747",
"types": [ "street_number" ]
}, {
"long_name": "Howard St",
"short_name": "Howard St",
"types": [ "route" ]
}, {
"long_name": "San Francisco",
"short_name": "San Francisco",
"types": [ "locality", "political" ]
}, {
"long_name": "San Francisco",
"short_name": "San Francisco",
"types": [ "administrative_area_level_2", "political" ]
}, {
"long_name": "California",
"short_name": "California",
"types": [ "administrative_area_level_1", "political" ]
}, {
"long_name": "94103",
"short_name": "94103",
"types": [ "postal_code" ]
} ],
"geometry": {
"location": {
"lat": 37.7831340,
"lng": -122.4030530
}
},
"rating": 3.7,
"url": "http://maps.google.com/maps/place?cid=13048026345962796583",
"icon": "http://maps.gstatic.com/mapfiles/place_api/icons/generic_business-71.png",
"reference": "CmRdAAAAXjPjnE6U3f7AhWjsg4oesR5iqD8pvugutrRgNZ5kvj_vg3W-9vsf7Br_YEbYY0LYyB7QezEJtJeRvZwo59Te-D_8i5ndaL87oF3aoQBrNWnKQLxmLAQoJF52BuIusy0mEhCzaRLFA1Tbxw3W36FXZWfJGhTvF5dmssLWmDH4gYFJ56tNfwXCog",
"id": "abbda52af18357b0575838ff00c7dd6ed69ed866"
},
"html_attributions": [ ]
}
The sample application will output the following, based on our java based model :
Perform Place Detail....
-------------------
Moscone Center - abbda52af18357b0575838ff00c7dd6ed69ed866 - CmRdAAAAPhQ4jEkrlFP3lMq8aixlj04pyv1iHWh055hezINwWUTjj4Z57SmnsBWs3qgwEoUjTBzIyUCwFWxIcgy5R0FyoeC_KrsJyaUO-ryPjkS2BDk4PzDBvtFy_dVJJxmWg038EhDxsgeS0t_7pmAfF4AErbV-GhSJDvgZsZ0pFcce9YtsnFewGsIk8A

Our java based object model looks like this :

package com.ecs.googleplaces.sample;

import com.google.api.client.util.Key;

public class PlaceDetail {

 @Key
 public Place result;

 @Override
 public String toString() {
  if (result!=null) {
   return result.toString();
  }
  return super.toString();
 }
}

Perform Autocomplete

The autocomplete API allows us to search for places by specifying a search query. It will "predict" places search results based on our (perhaps) incomplete search query.

The actual code to perform an autocomplete is done through the https://maps.googleapis.com/maps/api/place/autocomplete endpoint.

We provide the following parameters :

NameDescription
keyAPI Key.
inputThe text string on which to search. The Place service will return candidate matches based on this string and order results based on their perceived relevance.
locationThe latitude/longitude around which to retrieve Place information. This must be provided as a google.maps.LatLng object.
radiusThe distance (in meters) within which to return Place results. The recommended best practice is to set radius based on the accuracy of the location signal as given by the location sensor. Note that setting a radius biases results to the indicated area, but may not fully restrict results to the specified area.
sensorIndicates whether or not the Place Details request came from a device using a location sensor (e.g. a GPS). This value must be either true or false.

private static final String PLACES_AUTOCOMPLETE_URL = "https://maps.googleapis.com/maps/api/place/autocomplete/json?";
 

 public void performAutoComplete() throws Exception {
  try {
   System.out.println("Perform Autocomplete ....");
   System.out.println("-------------------------");
   
   HttpRequestFactory httpRequestFactory = createRequestFactory(transport);
   HttpRequest request = httpRequestFactory.buildGetRequest(new GenericUrl(PLACES_AUTOCOMPLETE_URL));
   request.url.put("key", API_KEY);
   request.url.put("input", "mos");
   request.url.put("location", latitude + "," + longitude);
   request.url.put("radius", 500);
   request.url.put("sensor", "false");
   PlacesAutocompleteList places = request.execute().parseAs(PlacesAutocompleteList.class);
   if (PRINT_AS_STRING) {
    System.out.println(request.execute().parseAsString());
   } else {
    for (PlaceAutoComplete place : places.predictions) {
     System.out.println(place);
    }
   }

  } catch (HttpResponseException e) {
   System.err.println(e.response.parseAsString());
   throw e;
  }
 } 

A sample response for all places resembling "mos" in San Fransisco looks like this (I've replaced the reference strings to make it more clear) :
{
"status": "OK",
"predictions": [ {
"description": "Moscone Center, Howard Street, San Francisco, CA, United States",
"types": [ "establishment" ],
"reference": "someRef",
"id": "abbda52af18357b0575838ff00c7dd6ed69ed866",
"terms": [ {
"value": "Moscone Center",
"offset": 0
}, {
"value": "Howard Street",
"offset": 16
}, {
"value": "San Francisco",
"offset": 31
}, {
"value": "CA",
"offset": 46
}, {
"value": "United States",
"offset": 50
} ],
"matched_substrings": [ {
"offset": 0,
"length": 3
} ]
}, {
"description": "The Moscone Center, San Francisco, CA, United States",
"types": [ "establishment" ],
"reference": "someRef",
"id": "3256e3f5f9e61141c3a6a9d423db72cbcc52a20d",
"terms": [ {
"value": "The Moscone Center",
"offset": 0
}, {
"value": "San Francisco",
"offset": 20
}, {
"value": "CA",
"offset": 35
}, {
"value": "United States",
"offset": 39
} ],
"matched_substrings": [ {
"offset": 4,
"length": 3
} ]
}, {
"description": "Mosser Co, 4th Street, San Francisco, CA, United States",
"types": [ "establishment" ],
"reference": "someRef",
"id": "f5bf41ca59341fa02820bfa372a30eace9554e6e",
"terms": [ {
"value": "Mosser Co",
"offset": 0
}, {
"value": "4th Street",
"offset": 11
}, {
"value": "San Francisco",
"offset": 23
}, {
"value": "CA",
"offset": 38
}, {
"value": "United States",
"offset": 42
} ],
"matched_substrings": [ {
"offset": 0,
"length": 3
} ]
}, {
"description": "Moss Street, San Francisco, CA, United States",
"types": [ "route", "geocode" ],
"reference": "someRef",
"id": "be49900f2870dc333d762b05acb2d3fb306da7c6",
"terms": [ {
"value": "Moss Street",
"offset": 0
}, {
"value": "San Francisco",
"offset": 13
}, {
"value": "CA",
"offset": 28
}, {
"value": "United States",
"offset": 32
} ],
"matched_substrings": [ {
"offset": 0,
"length": 3
} ]
}, {
"description": "Moscone Center Garage, 3rd Street, San Francisco, CA, United States",
"types": [ "establishment" ],
"reference": "someRef",
"terms": [ {
"value": "Moscone Center Garage",
"offset": 0
}, {
"value": "3rd Street",
"offset": 23
}, {
"value": "San Francisco",
"offset": 35
}, {
"value": "CA",
"offset": 50
}, {
"value": "United States",
"offset": 54
} ],
"matched_substrings": [ {
"offset": 0,
"length": 3
} ]
} ]
}


The code outputs the following :

Perform Autocomplete ....
-------------------------
Moscone Center, Howard Street, San Francisco, CA, United States - abbda52af18357b0575838ff00c7dd6ed69ed866 - CnRtAAAAShblGHcmcJigrSznSRTAbwMF9JdgmkD_0lxxXV78pMRndcO8fCgmNWdfq80jihJASCAV4jU2HzTmLkXXJvvDZi886vkgXWU5CvRy64Nt3-212qUNrR_a_-3rW11vIODVbjge-gSdkgoRDlYGHB1iIxIQuQQuI76fmECX0Nl0r-FDZxoUiB-QygoIJi-aUDk80XvYsgUOgYk
The Moscone Center, San Francisco, CA, United States - 3256e3f5f9e61141c3a6a9d423db72cbcc52a20d - CnRiAAAA9ZN99q5GQ-rZKRSf_3c9DVxJp0EGwZyY5Fad0W1RAFnBS3BfUxBHrOqNTpZ9LLx-Vl8erDFYRSn-eEGHjHFgTcgjGJs6ojVkkmeCR-AtpOepGFOVoaWXo2-UfOI1JJrFxPZgL3RnYQzKhEbRK4KDUhIQDtbLD5M_jtZTsabOrm0vShoUDbaJ6-WxjVagtZ8fiLmwr_ZpfqQ
Mosser Co, 4th Street, San Francisco, CA, United States - f5bf41ca59341fa02820bfa372a30eace9554e6e - CnRlAAAA48pjj_vpFfZwIM0bUakPgCIU9EsdrjMtWLPMjbw39lapiz6DN6qlKBMP_PQQKqP-5ju6JU8r1Qnw8M-ddH5ZW2v78sFyqCPzpiP6OMRlhuOBOgmsaMxOxqbkZoMvb5EKBe2jM2RHSb69CtChDrKBGxIQMqVs3Mn2uZ2wDzp-KqgvYxoUPX_hvkzXNZ8lAqp9BTgAJjYlCpE
Moss Street, San Francisco, CA, United States - be49900f2870dc333d762b05acb2d3fb306da7c6 - CmRbAAAAHA39Lo-1I8KJhKFYIETdqtu9byFGvzdItkrosiR99clok2OAw0ZrnRiaHwXirkF4Cths3jfsWNF6KJelbWHvp9GJKMZBDD8uVsGVmfStMtBjtW173jHKzRKQPlnyNoR-EhDWP8G0v4ZrLUXrUEgF8EmaGhSaPajMDDjfBPt0Ej3pCg0d1RHEkA
Moscone Center Garage, 3rd Street, San Francisco, CA, United States - f2d897f9f68a31861b864c4035ab0eca1db933c9 - CoQBcQAAADPHf6P13LwU4_8FrAaRNr9qlCZNglkPE1lR70pSuTVYqPwr02MDGgMKauD4A5Q3Tqx8tQjxM546RBu3CWPabS7gfG9zl_n8WI_b5jKn7HMjQA2XPShS3YvuvtblidVvB5UNcLNbdUoulyR7zeXrpiVowsT_1LfXlumTv45UDy_CEhC3ZQ1AZ2Scm-9Mr9S_NCoVGhRm5nitiMq83B7Ng619at7iu-nPHQ

We've convered the JSON response into a Java based model using the PlacesAutocompleteList class.

package com.ecs.googleplaces.sample;

import java.util.List;

import com.google.api.client.util.Key;

public class PlacesAutocompleteList {

 @Key
 public List<PlaceAutoComplete> predictions;

 public static class PlaceAutoComplete {

  @Key
  public String id;

  @Key
  public String description;

  @Key
  public String reference;

  @Override
  public String toString() {
   return description + " - " + id + " - " + reference;
  }

 }
}

Other API calls supported by the API


Place Check-Ins

Once you have a reference from a Place Search request, you can use it to indicate that a user has checked in to that Place. Check-in activity from your application is reflected in the Place search results that are returned - popular establishments are ranked more highly, making it easy for your users to find likely matches.

Note: this is not related to the Google Maps / Latitude API check-ins concept. It's used for an internal ranking within you application.

Place Report requests

Place Report requests are used to add new Places, or delete existing ones.

Conclusions

It's been a long wait, but we can finally start coding against the Places API. Location aware applications can now leverage the Places API to provide "check-in" or other places related activities in their applications. Using the Google APIs Client Library for Java, getting Google Places up and running in a custom Android application also becomes a breeze.

References

37 comments:

  1. Hi,

    I am currently working with the Google Places API to get the list of places around my current location. I have got it to work but I am unable to get the "lat" and "lng" value under geometry - location. Can you help me with my problem?

    Thanks.

    ReplyDelete
  2. Great tutorial, was a great help for me when using Google Geocoding API with the google-api-java-client.
    Thank you.

    ReplyDelete
  3. Where is the android manifest file and res folders? I downloaded your project from github and found most of the files missing.

    ReplyDelete
  4. The sample code is a J2SE example (plain java) just to illustrate the API. It can however be embedded in an Android app without many changes. The only thing you would need to change is to either use the AccountManager (=ClientLogin) or oAuth for security.

    ReplyDelete
  5. To correct my comment above, there is no need to implement AccountManager (ClientLogin) or OAuth for the Places API. You just need an API key, but no authentication is required.

    ReplyDelete
  6. This comment has been removed by the author.

    ReplyDelete
  7. What does the @key annotation mean? It brings up errors when I try to compile it.

    ReplyDelete
  8. The @Key annotation is part of the google-api-client-1.4.1-beta.jar file, and is used to specify that a field in your model is a data key, optionally providing the data key name.

    That data key is mapped to a JSON key. You basically use it to parse the responses, and inject the JSON keys in your java model.

    ReplyDelete
  9. Thanks for the post. I can't figure out how the Place class would wrap the "geometry" info from the JSON response. It consists of a location lat/lng, and I think two optional viewport lat/lng's. Do you have an example of that?

    ReplyDelete
  10. Scratch that request. I got it. Your later post on 7-17 helped: http://ddewaele.blogspot.com/2011_07_17_archive.html

    I'm not sure why the classes need to be static, but if you look at the exception it was throwing it clearly says it wants them static.

    ReplyDelete
  11. Do you know if there is anyway of increasing the number of results on the places api search from its default of a maximum of 20. If not what approach would you recommend for achieving the equivalent of say 150 results for a given query.

    ReplyDelete
  12. Google place API does not work in Bangladesh, maybe you should give some US location.Now what ca i do?
    I searched for restaurants:
    https://maps.googleapis.com/maps/api/place/search/xml?location=23.709921,90.407143&radius=2000&types=restaurant&sensor=false&key=AIzaSyAB-dwfPHYylEYEUn0Bg74lB1ogi-jCKBs

    ReplyDelete
  13. Hi,

    Thanks for the example, It would be great if you could post the android code for the same.

    ReplyDelete
  14. Hi,
    I can't use this in version 1.6.0-beta:
    request.url.put("key", API_KEY);
    I must make url manual :(
    there're another way?
    Thanks!!

    ReplyDelete
  15. I make an android demo here ^^
    https://github.com/tuthan/Google-Place-Api-Demo

    ReplyDelete
  16. A question: if I have to get lat and lng values, since geometry is a multidim. struct:
    "geometry" : {
    "location" : {
    "lat" : -33.8722580,
    "lng" : 151.1986550
    }
    },
    How should I write Place.class code to get lat and lng values?

    Thanks in advance.

    Luca

    ReplyDelete
  17. It seems the api have changed which required me to make a couple of achievements. I can search for places and print the result as a string but when I try call:

    PlacesList places = request.execute().parseAs(PlacesList.class);

    I get a null pointer exception:


    com.google.api.client.http.json.JsonHttpParser.parserForResponse(JsonHttpParser.java:118)

    Note one of the changes I had to make was change

    JsonHttpParser parser = new JsonHttpParser();
    parser.jsonFactory = new JacksonFactory();

    To

    JsonHttpParser parser = new JsonHttpParser(new JsonFactory() {

    @Override
    public JsonParser createJsonParser(Reader arg0) throws IOException {
    // TODO Auto-generated method stub
    return null;
    }

    @Override
    public JsonParser createJsonParser(String arg0) throws IOException {
    // TODO Auto-generated method stub
    return null;
    }

    @Override
    public JsonParser createJsonParser(InputStream arg0) throws IOException {
    // TODO Auto-generated method stub
    return null;
    }

    @Override
    public JsonGenerator createJsonGenerator(OutputStream arg0,
    JsonEncoding arg1) throws IOException {
    // TODO Auto-generated method stub
    return null;
    }

    @Override
    public JsonGenerator createJsonGenerator(Writer arg0) throws IOException {
    // TODO Auto-generated method stub
    return null;
    }
    });

    ReplyDelete
  18. Hey! Here is something I observed : the distance between the location i sent and the location of the result is more than the radius i sent in the query.... and its not a small difference, the distance is nearly double the radius!

    Did you see anything like that?

    ReplyDelete
  19. A question: if I have to get lat and lng values, since geometry is a multidim. struct:
    "geometry" : {
    "location" : {
    "lat" : -33.8722580,
    "lng" : 151.1986550
    }
    },
    How should I write Place.class code to get lat and lng values?

    ReplyDelete
    Replies
    1. Write your Place.class as such:

      public class Place {

      @Key
      public Result result;

      public static class Result {

      @Key
      public String id;

      @Key
      public String formatted_address;

      @Key
      public String reference;

      @Key
      public String name;

      @Key
      public PlaceGeometry geometry;
      }

      public static class PlaceGeometry {
      @Key
      public Location location;
      }

      public static class Location {
      @Key
      public double lat;

      @Key
      public double lng;
      }
      }

      Delete
    2. made the place class like you mentioned in above but still now i am not getting the lat and long. could help me out from this issue

      Delete
    3. Aside from not still not getting lat and long, after following that set-up I can no longer access id and name.

      Delete
    4. I finally got it to work. Another post from this same blog helped: http://ddewaele.blogspot.com/2011_07_17_archive.html

      Anyway as for the code, just add the following to the Place class:

      @Key
      public Geometry geometry;

      public static class Geometry {
      @Key
      public Location location;
      }

      public static class Location {
      @Key
      public double lat;

      @Key
      public double lng;

      public String toString() {
      return Double.toString(lat) + ", " + Double.toString(lng);
      }
      }

      Delete
  20. I download the source code from https://github.com/tuthan/Google-Place-Api-Demo, along with necessary libraries, but on importing Google API Client Library for Java it is supposed to be not importing as the code give me compile time errors on all imports from that libraries.
    e.g. all below imports give me compile time errors.

    import com.google.api.client.googleapis.GoogleHeaders;
    import com.google.api.client.http.GenericUrl;
    ......etc

    Though i have import the library correctly as we do in eclipse for android. please help me out as i am tired of resolving this issue :(

    ReplyDelete
    Replies
    1. If you're still interested, I was able to make that application work as intended.

      What I did was instead of adding the java-api-client as a whole (meaning the zip file),
      I extracted first the contents of the java-api-client zip and then added those individual files to the project's build path.

      Additionally, taken from the 'dependencies' folder,
      I also added the following jars to the build path:
      - guava-r09
      - guava-r09-sources
      - jackson-core-asl-1.9.1
      - jackson-core-asl-1.9.1-sources

      * Take note not to add all the JARs from the dependencies folder as that will give you an error.

      Delete
  21. hi , Iam trying to develop an application in Android which provides Google check-in ..can anybody plz help me out with this...:(

    ReplyDelete
  22. This comment has been removed by the author.

    ReplyDelete
  23. Hi, I want to display the pictures of places. How can I get the places pictures?

    ReplyDelete
  24. HI AndroidDev~ I think I saw in this blog that solution for your problem.
    Try to browse more in this blog.

    Oh my~ I feel some headache seeing those codes. >.<

    Vivian
    My blog : aménagement placard 

    ReplyDelete
  25. Can someone please help me with the steps of creating this as an android application...i downloaded the library now how do I use it...plz I hav a project submission in a week and i m really struggling please help me someone!!!

    ReplyDelete
  26. Please help me sir I really need the help my career depends on my final year project

    ReplyDelete
  27. I haven't been able to get this to work yet.

    I created a new project, used Git to download the files from github.com/ddewaele/GooglePlacesApi, and copied the downloaded GitHub files into their appropriate locations in my project. Unfortunately, I'm now getting an error for all of the "import com.google.api.client.*" statements. The error message is "The import com.google.api cannot be resolved". What do I need to do next?

    ReplyDelete
  28. thanks to give me a code source of application

    ReplyDelete
  29. Nice post , good job!

    If you want to know how to integrate google places API with Wikipedia & Wikitravel please visit my blog

    http://braintechie.blogspot.co.uk/2012/11/integrating-google-places-apis-with.html

    ReplyDelete
  30. For people looking for tutorial you may checkout this as well..

    Developing a mobile trip planning app with Google Places API - Step by step tutorial

    http://braintechie.blogspot.co.uk/2012/12/developing-mobile-trip-planning-app.html

    ReplyDelete
  31. Hello,

    can someone tell me how I would parse out the JSONArray types that is nested in the JSONArray results using the Google APIs client for java?

    ReplyDelete
  32. Davy,

    Your example is almost exactly what I am looking for as a starting point for using the google place. Unfortunately I am not able to run the code because most functions are deprecated in the with the new google API. Do you have new version for these awesome codes?

    THanks.

    shajia.xie@gmail.com

    ReplyDelete