8.1: Places API
Contents:
- Introduction
- Using the place-picker UI
- Getting the device's current place
- Using the place-autocomplete service
- Getting place photos
- Using the place ID
- Getting place details
- Related practical
- Learn more
The Location API is great for providing your app with the device's current location and requesting periodic updates. However, the Location API falls short when you need details about a location, or when you need to allow the user to search for a specific place that's not tied to the device location.
A place is defined as a physical space that has a name. Another way of thinking about a place is that it's anything you can find on a map. Examples include local businesses, points of interest, and geographic locations.
In the Google Places API for Android, a Place object represents a place. A Place object can include the place's name and address, geographical location, place ID, phone number, place type, website URL, and more.
There are several ways to access the Places API:
- The place-picker UI lets users select a place on an interactive map.
- The
PlaceDetectionClientinterface provides quick access to a device's current place and the place's details. - The
GeoDataClientinterface provides access to Google's database of local place and business information, including high-quality images. - The place-autocomplete service provides a UI element that lets a user search for a specific place with autocomplete suggestions. You can also build your own autocomplete UI and use place-autocomplete API calls.
To include the Places API in your app, you must add a dependency to your app-level build.gradle file and set up an API key. These steps are described in the related practical for this lesson.
Using the place-picker UI

The PlacePicker provides a UI dialog that displays an interactive map and a list of nearby places. Users choose a place by selecting the place on a map or by searching for the place. Your app can then retrieve the details of the selected place.
The place picker requires the ACCESS_FINE_LOCATION permission.
Launching the place-picker UI
To use the place-picker UI, complete the following steps:
- Use the
PlacePicker.IntentBuilder()to construct anIntent. If you want to change the default latitude and longitude bounds of the map that the place picker displays, call
setLatLngBounds()on the builder. Pass in aLatLngBoundsobject.The bounds that you set in the
LatLngBoundsobject define an area called the viewport . By default, the viewport is centered on the device's location, with the zoom at city-block level.Call
startActivityForResult(). Pass in the intent and a predefined request code. The request code lets you identify the request when the result is returned.PlacePicker.IntentBuilder builder = new PlacePicker.IntentBuilder(); try { // Launch the PlacePicker. startActivityForResult(builder.build(MainActivity.this) , REQUEST_PICK_PLACE); } catch (GooglePlayServicesRepairableException | GooglePlayServicesNotAvailableException e) { e.printStackTrace(); }
Obtaining the selected place
Once the user has selected a place in the place-picker dialog, your activity's onActivityResult() method is called. The onActivityResult() method uses the integer request code you used in startActivityForResult().
To retrieve the place, call PlacePicker.getPlace() in onActivityResult(). Pass in the activity context and the data Intent. If the user has not selected a place, the method returns null.
You can also retrieve the most recent bounds of the map by calling PlacePicker.getLatLngBounds().
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (resultCode == RESULT_OK) {
Place place = PlacePicker.getPlace(this, data);
setAndroidType(place);
mLocationTextView.setText(
getString(R.string.address_text, place.getName(),
place.getAddress(), System.currentTimeMillis()));
} else {
mLocationTextView.setText(R.string.no_place);
}
super.onActivityResult(requestCode, resultCode, data);
}
Getting the device's current place
To get information about the device's current location, call the PlaceDetectionClient.getCurrentPlace() method. Optionally, pass in a PlaceFilter instance. (Filtering is described below, in Filtering the list of places.)
The getCurrentPlace() method returns a Task that contains a PlaceLikelihoodBuffer. The PlaceLikelihoodBuffer contains a list of PlaceLikelihood objects that represent likely Place objects. If no known place corresponds to the filter criteria, the buffer may be empty.
- To retrieve a
Placeobject, callPlaceLikelihood.getPlace(). - Each place result includes an indication of the likelihood that the place is the right one. To get the place's likelihood value, call
PlaceLikelihood.getLikelihood().
About the likelihood values:
- A place's likelihood value is the relative probability that this place is the best match within the list of returned places for a single request. You can't compare likelihoods across different requests.
- The value of the likelihood is between 0 and 1.0. A higher likelihood value means a greater probability that the place is the best match.
- The sum of the likelihoods in a given
PlaceLikelihoodBufferis always less than or equal to 1.0. The sum isn't necessarily 1.0.
For example, there might be a 55% likelihood that the correct place is place A and a 35% likelihood that the correct place is place B. To represent this scenario, the PlaceLikelihoodBuffer has two members: Place A with a likelihood of 0.55, and Place B with a likelihood of 0.35.
PlaceLikelihoodBuffer object when your app no longer needs it. Read more about handling buffers.
Task<PlaceLikelihoodBufferResponse> placeResult =
mPlaceDetectionClient.getCurrentPlace(null);
placeResult.addOnCompleteListener
(new OnCompleteListener<PlaceLikelihoodBufferResponse>() {
@Override
public void onComplete(@NonNull
Task<PlaceLikelihoodBufferResponse> task) {
// If you get a result, get the most likely place and
// update the place name.
if (task.isSuccessful()) {
PlaceLikelihoodBufferResponse likelyPlaces =
task.getResult();
float maxLikelihood = 0;
Place currentPlace = null;
for (PlaceLikelihood placeLikelihood : likelyPlaces) {
if (maxLikelihood < placeLikelihood.getLikelihood())
{
maxLikelihood = placeLikelihood.getLikelihood();
currentPlace = placeLikelihood.getPlace();
}
}
likelyPlaces.release();
// Update the UI.
if (currentPlace != null) {
mLocationTextView.setText(
getString(R.string.address_text,
currentPlace.getName(), result,
System.currentTimeMillis()));
setAndroidType(currentPlace);
}
// Otherwise, show an error.
} else {
mLocationTextView.setText(
getString(R.string.address_text,
getString(R.string.no_place),
result, System.currentTimeMillis()));
}
}
});
Filtering the list of places
To limit the results that the PlaceLikelihoodBuffer includes when you request information about the device's current place, use a PlaceFilter.
- To limit the results to places that are currently open, pass
trueas the first parameter in thePlaceFilter. - To limit the results to places that match certain place IDs, pass in the place IDs as the second parameter in the
PlaceFilter. Provide the place IDs as aCollectionof strings.
Using the place-autocomplete service
The Places API provides a PlaceAutocomplete service that returns Place predictions based on user search queries. As the user types, the autocomplete service returns suggestions for places such as businesses, addresses, and points of interest.
You can add the place-autocomplete service to your app in either of the following ways:
- Use the autocomplete UI, as described below. This approach saves development time and ensures a consistent user experience.
- Get place predictions programmatically, as described in Getting place predictions programmatically. With this approach, you can create a customized user experience.
Adding an autocomplete UI element
The autocomplete UI is a search dialog with built-in autocomplete functionality. As a user enters search terms, the search dialog presents a list of predicted places to choose from. When the user makes a selection, a Place instance is returned. Your app can use the Place instance to get details about the selected place.

There are two ways to add the autocomplete UI to your app:
- Option 1: Embed a
PlaceAutocompleteFragmentfragment, as described below. - Option 2: If you want to launch the autocomplete activity from someplace other than a search dialog, use an intent to launch the autocomplete activity, as described in Using an intent to launch the autocomplete activity.
Embedding a PlaceAutocompleteFragment fragment
To add a PlaceAutocompleteFragment to your app, take the following steps:
Add a fragment to your activity's XML layout, with the
android:nameattribute set tocom.google.android.gms.location.places.ui.PlaceAutocompleteFragment.<fragment android:id="@+id/place_autocomplete_fragment" android:layout_width="match_parent" android:layout_height="wrap_content" android:name="com.google.android.gms.location.places.ui.PlaceAutocompleteFragment" />Note: By default, the fragment has no border or background. To provide a consistent visual appearance, nest the fragment within another layout element such as aCardView.Add a listener to your activity or fragment.
The
PlaceSelectionListenerhandles returning a place in response to the user's selection. The following code creates a reference to the fragment and adds a listener to thePlaceAutocompleteFragment:PlaceAutocompleteFragment autocompleteFragment = (PlaceAutocompleteFragment)getFragmentManager() .findFragmentById(R.id.place_autocomplete_fragment); autocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() { @Override public void onPlaceSelected(Place place) { // TODO: Get info about the selected place. Log.i(TAG, "Place: " + place.getName()); } @Override public void onError(Status status) { // TODO: Handle the error. Log.i(TAG, "An error occurred: " + status); } });
Using an intent to launch the autocomplete activity
You might want your app to use a navigational flow that's different from what the autocomplete UI provides. For example, your app might trigger the autocomplete experience from an icon, rather than from a search field.
To launch the autocomplete activity from someplace other than the default autocomplete search dialog, use an intent:
- Use
PlaceAutocomplete.IntentBuilderto create an intent. Pass in the desiredPlaceAutocompletedisplay mode—you can choose overlay or full-screen. The intent must callstartActivityForResult(), passing in a request code that identifies your intent.int PLACE_AUTOCOMPLETE_REQUEST_CODE = 1; ... try { Intent intent = new PlaceAutocomplete.IntentBuilder(PlaceAutocomplete.MODE_FULLSCREEN) .build(this); startActivityForResult(intent, PLACE_AUTOCOMPLETE_REQUEST_CODE); } catch (GooglePlayServicesRepairableException e) { // TODO: Handle the error. } catch (GooglePlayServicesNotAvailableException e) { // TODO: Handle the error. } Override the
onActivityResult()method to receive the selected place. When a user has selected a place, check for the request code that you passed into your intent. For example:@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == PLACE_AUTOCOMPLETE_REQUEST_CODE) { if (resultCode == RESULT_OK) { Place place = PlaceAutocomplete.getPlace(this, data); Log.i(TAG, "Place: " + place.getName()); } else if (resultCode == PlaceAutocomplete.RESULT_ERROR) { Status status = PlaceAutocomplete.getStatus(this, data); // TODO: Handle the error. Log.i(TAG, status.getStatusMessage()); } else if (resultCode == RESULT_CANCELED) { // The user canceled the operation. } } }Restricting the search results
You can set the autocomplete search to bias results to a geographic region. You can also filter the results to one or more place types.
To bias autocomplete results to a geographic region, call setBoundsBias() off your app's PlaceAutocompleteFragment instance, or off your app's IntentBuilder instance. Pass in a LatLngBounds object.
The following code calls setBoundsBias() on a fragment instance. The code biases the fragment's autocomplete suggestions to a region of Sydney, Australia.
autocompleteFragment.setBoundsBias(new LatLngBounds(
new LatLng(-33.880490, 151.184363),
new LatLng(-33.858754, 151.229596)));
To filter autocomplete results to a specific place type, call AutocompleteFilter.Builder to create a new AutocompleteFilter. Call setTypeFilter() to set the filter to use. Then, pass the filter to the fragment or intent.
The following code sets an AutocompleteFilter on a PlaceAutocompleteFragment. The filter returns only results that have precise addresses.
AutocompleteFilter typeFilter = new AutocompleteFilter.Builder()
.setTypeFilter(AutocompleteFilter.TYPE_FILTER_ADDRESS)
.build();
autocompleteFragment.setFilter(typeFilter);
The following code sets the same AutocompleteFilter on an intent instead of on a fragment:
AutocompleteFilter typeFilter = new AutocompleteFilter.Builder()
.setTypeFilter(AutocompleteFilter.TYPE_FILTER_ADDRESS)
.build();
Intent intent =
new PlaceAutocomplete.IntentBuilder(PlaceAutocomplete.MODE_FULLSCREEN)
.setFilter(typeFilter)
.build(this);
For information about place types, see the guide to place types and the AutocompleteFilter.Builder documentation.
To filter autocomplete results to a specific country:
- Call
AutocompleteFilter.Builderto create a newAutocompleteFilter. - Call
setCountry()to set the country code. - Pass the filter to a fragment or intent.
The following code sets an AutocompleteFilter on a PlaceAutocompleteFragment. The filter returns only results within the specified country.
AutocompleteFilter typeFilter = new AutocompleteFilter.Builder()
.setCountry("AU")
.build();
autocompleteFragment.setFilter(typeFilter);
Getting place predictions programmatically
You can create a custom search UI instead of using the Places API UI. To do this, your app must get place predictions programmatically.
To get a list of predicted place names or addresses from the autocomplete service, call GeoDataClient.getAutocompletePredictions(). Pass in the following parameters:
- A query string containing the text typed by the user.
- A
LatLngBoundsobject that biases the results to a specific area specified by latitude and longitude bounds. - Optional: To restrict the results to one or more types of place, include an
AutocompleteFilterthat contains a set of place types.
The API returns an AutocompletePredictionBuffer in a Task. The AutocompletePredictionBuffer contains a list of AutocompletePrediction objects that represent predicted places. If no known place corresponds to the query and the filter criteria, the buffer may be empty.
AutocompletePredictionBuffer object when your app no longer needs it. Read more about handling buffers.
For each predicted place, you can call the following methods to retrieve place details:
getPrimaryText(CharacterStyle matchStyle)returns the primary text that describes a place. This text is usually the name of the place, for example, "Eiffel Tower" or "123 Pitt Street."getSecondaryText(CharacterStyle matchStyle)returns the secondary text that describes a place. For example, "Avenue Anatole France, Paris, France," or "Sydney, New South Wales." Secondary text is useful as a second line of text when showing autocomplete predictions.getFullText(CharacterStyle matchStyle)returns the full text of a place description. This description combines the primary and secondary text. For example, "Eiffel Tower, Avenue Anatole France, Paris, France." To highlight sections of the description that match the search, include aCharacterStyleparameter. Set the parameter tonullif you don't need any highlighting.getPlaceId()returns the place ID of the predicted place. A place ID is a textual identifier that uniquely identifies a place. You can use the place ID to retrieve thePlaceobject later.getPlaceTypes()returns the list of place types associated with this place.
About usage limits on place predictions
When you get a place prediction programmatically, usage limits apply. In particular, the GeoDataClient.getAutocompletePredictions() method is subject to tiered query limits. For details, see Usage Limits.
Displaying attributions in your app
- If your app uses the autocomplete service programmatically, your UI must display a "Powered by Google" attribution, or your UI must appear within a Google-branded map.
- If your app uses the autocomplete UI, you don't need to do anything special, because the required attribution is displayed by default.
- If you retrieve and display additional place information after getting a place by ID, you must display third-party attributions.
For more details, see Displaying Attributions.
Getting place photos
You can use the Places API to request place photos to display in your app. The photos come from several sources, including business owners and Google+ users. To retrieve photos for a place, take the following steps:
- Call
GeoDataClient.getPlacePhotos(), passing a string with a place ID. This method returns aPlacePhotoMetadataResultinstance in aTask. - Call
getPhotoMetadata()on thePlacePhotoMetadataResultinstance. The method returns aPlacePhotoMetadataBufferthat holds a list ofPlacePhotoMetadatainstances. The list includes onePlacePhotoMetadatainstance for each photo. Call
get()on thePlacePhotoMetadataBufferinstance. Pass in an integer to retrieve thePlacePhotoMetadatainstance at the given index.- To return a bitmap image, call either
PlacePhotoMetadata.getPhoto(), orPlacePhotoMetadata.getScaledPhoto()on aPlacePhotoMetadatainstance. - To return attribution text, call
PlacePhotoMetadata.getAttributions()on aPlacePhotoMetadatainstance.
- To return a bitmap image, call either
The Places API requires network access, therefore all calls must be made in the background, off the main UI thread. For this reason, retrieve the photos in the background asynchronously.
About usage limits on place photos
When you get place photos programmatically, usage limits apply. Retrieving an image costs one unit of quota. There are no usage limits for retrieving photo metadata.
For more information, see Usage Limits.
Displaying attributions in your app
In most cases, place photos can be used without attribution, or the required attribution is included as part of the image. However, if a PlacePhotoMetadata instance includes an attribution, you must include the attribution in your app wherever you display the image.
For more information, see Displaying Attributions.
Using the place ID
A place ID is a textual identifier that uniquely identifies a place. To retrieve a place's ID:
- Call
Place.getId(). - The place-autocomplete service also returns a place ID for each place that matches the supplied search query and filter.
Store the place ID and use it to retrieve the Place object again later.
To get a place by its ID:
- Call
GeoDataClient.getPlaceById(), passing in one or more place IDs. - The API returns a
PlaceBufferin aTask. ThePlaceBufferdata structure contains a list ofPlaceobjects that match the supplied place IDs.mGeoDataClient.getPlaceById(placeId).addOnCompleteListener(new OnCompleteListener<PlaceBufferResponse>() { @Override public void onComplete(@NonNull Task<PlaceBufferResponse> task) { if (task.isSuccessful()) { PlaceBufferResponse places = task.getResult(); Place myPlace = places.get(0); Log.i(TAG, "Place found: " + myPlace.getName()); places.release(); } else { Log.e(TAG, "Place not found."); } } });
Getting place details
The Place object provides information about a specific place. You can get a Place object in the following ways:
- Call
PlaceDetectionClient.getCurrentPlace(). For details about this process, see Current Place. - Add the
PlacePickerUI, then callPlacePicker.getPlace(). - Call
GeoDataClient.getPlaceById(). For more information, see Get a place by ID.
Use the following methods to retrieve data from a Place object:
getName(): The place's name.getAddress(): The place's address, in human-readable format.getID(): The textual identifier for the place, as described in Using the place ID.getPhoneNumber(): The place's phone number.getWebsiteUri(): The URI of the place's website, if known. This website is maintained by the business or other entity associated with the place. Returnsnullif no website is known.getLatLng(): The geographical location of the place, specified as latitude and longitude coordinates.getViewport(): A viewport, returned as aLatLngBoundsobject, useful for displaying the place on a map. If the size of the place is not known, this method may returnnull.getLocale(): The locale for which the name and address are localized.getPlaceTypes(): A list of place types that characterize this place. For a list of available place types, see thePlaceconstant documentation.getPriceLevel(): The price level for this place, returned as an integer with values ranging from 0 (cheapest) to 4 (most expensive).getRating(): An rating of the place, returned as afloatwith values ranging from 1.0 to 5.0, based on aggregated user reviews.
Related practical
The related practical documentation is in 8.1: Using the Places API.
Learn more
Android developer documentation: