Place Autocomplete

The autocomplete service in the Places SDK for Android returns place predictions in response to user search queries. As the user types, the autocomplete service returns suggestions for places such as businesses, addresses, plus codes, and points of interest.

You can add autocomplete to your app in the following ways:

Add an autocomplete widget

The autocomplete widget is a search dialog with built-in autocomplete functionality. As a user enters search terms, the widget presents a list of predicted places to choose from. When the user makes a selection, a Place instance is returned, which your app can then use to get details about the selected place.

There are two options for adding the autocomplete widget to your app:

Option 1: Embed an AutocompleteSupportFragment

To add an AutocompleteSupportFragment to your app, take the following steps:

  1. Add a fragment to your activity's XML layout.
  2. Add a listener to your activity or fragment.

Add AutocompleteSupportFragment to an activity

To add AutocompleteSupportFragment to an activity, add a new fragment to an XML layout. For example:

<fragment android:id="@+id/autocomplete_fragment"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:name="com.google.android.libraries.places.widget.AutocompleteSupportFragment"
  />
  • By default, the fragment has no border or background. To provide a consistent visual appearance, nest the fragment within another layout element such as a CardView.
  • If you are using the Autocomplete fragment, and need to override onActivityResult, you must call super.onActivityResult, otherwise the fragment will not function properly.

Add a PlaceSelectionListener to an activity

The PlaceSelectionListener handles returning a place in response to the user's selection. The following code shows creating a reference to the fragment and adding a listener to your AutocompleteSupportFragment:

Java

    // Initialize the AutocompleteSupportFragment.
    AutocompleteSupportFragment autocompleteFragment = (AutocompleteSupportFragment)
        getSupportFragmentManager().findFragmentById(R.id.autocomplete_fragment);

    // Specify the types of place data to return.
    autocompleteFragment.setPlaceFields(Arrays.asList(Place.Field.ID, Place.Field.NAME));

    // Set up a PlaceSelectionListener to handle the response.
    autocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
        @Override
        public void onPlaceSelected(@NotNull Place place) {
            // TODO: Get info about the selected place.
            Log.i(TAG, "Place: " + place.getName() + ", " + place.getId());
        }


        @Override
        public void onError(@NotNull Status status) {
            // TODO: Handle the error.
            Log.i(TAG, "An error occurred: " + status);
        }
    });
      

Kotlin

    // Initialize the AutocompleteSupportFragment.
    val autocompleteFragment =
        supportFragmentManager.findFragmentById(R.id.autocomplete_fragment)
            as AutocompleteSupportFragment

    // Specify the types of place data to return.
    autocompleteFragment.setPlaceFields(listOf(Place.Field.ID, Place.Field.NAME))

    // Set up a PlaceSelectionListener to handle the response.
    autocompleteFragment.setOnPlaceSelectedListener(object : PlaceSelectionListener {
        override fun onPlaceSelected(place: Place) {
            // TODO: Get info about the selected place.
            Log.i(TAG, "Place: ${place.name}, ${place.id}")
        }

        override fun onError(status: Status) {
            // TODO: Handle the error.
            Log.i(TAG, "An error occurred: $status")
        }
    })
      

Option 2: Use an intent to launch the autocomplete activity

If you want your app to use a different navigational flow (for example, to trigger the autocomplete experience from an icon rather than a search field), your app can launch autocomplete by using an intent.

To launch the autocomplete widget using an intent, follow these steps:

  1. Use Autocomplete.IntentBuilder to create an intent, passing the desired Autocomplete mode. The intent must call startActivityForResult, passing in a request code that identifies the intent.
  2. Override the onActivityResult callback to receive the selected place.

Create an autocomplete intent

The example below shows using Autocomplete.IntentBuilder to create an intent to launch the autocomplete widget as an intent:

Java

    private static int AUTOCOMPLETE_REQUEST_CODE = 1;

    // Set the fields to specify which types of place data to
    // return after the user has made a selection.
    List<Place.Field> fields = Arrays.asList(Place.Field.ID, Place.Field.NAME);

    // Start the autocomplete intent.
    Intent intent = new Autocomplete.IntentBuilder(AutocompleteActivityMode.FULLSCREEN, fields)
        .build(this);
    startActivityForResult(intent, AUTOCOMPLETE_REQUEST_CODE);
      

Kotlin

    private val AUTOCOMPLETE_REQUEST_CODE = 1

    // Set the fields to specify which types of place data to
    // return after the user has made a selection.
    val fields = listOf(Place.Field.ID, Place.Field.NAME)

    // Start the autocomplete intent.
    val intent = Autocomplete.IntentBuilder(AutocompleteActivityMode.FULLSCREEN, fields)
        .build(this)
    startActivityForResult(intent, AUTOCOMPLETE_REQUEST_CODE)
      

When using an intent to launch the autocomplete widget, you can choose from overlay or full-screen display modes. The following screenshots show each display mode respectively:

When displayed in overlay mode, the autocomplete widget appears superimposed over the calling UI.
Figure 1: Autocomplete widget in OVERLAY mode
When displayed in fullscreen mode, the autocomplete widget fills the entire screen.
Figure 2: Autocomplete widget in FULLSCREEN mode

Override the onActivityResult callback

To receive a notification when the user has selected a place, your app should override the activity's onActivityResult(), checking for the request code you have passed for your intent, as shown in the following example.

Java

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    if (requestCode == AUTOCOMPLETE_REQUEST_CODE) {
        if (resultCode == RESULT_OK) {
            Place place = Autocomplete.getPlaceFromIntent(data);
            Log.i(TAG, "Place: " + place.getName() + ", " + place.getId());
        } else if (resultCode == AutocompleteActivity.RESULT_ERROR) {
            // TODO: Handle the error.
            Status status = Autocomplete.getStatusFromIntent(data);
            Log.i(TAG, status.getStatusMessage());
        } else if (resultCode == RESULT_CANCELED) {
            // The user canceled the operation.
        }
        return;
    }
    super.onActivityResult(requestCode, resultCode, data);
}
      

Kotlin

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    if (requestCode == AUTOCOMPLETE_REQUEST_CODE) {
        when (resultCode) {
            Activity.RESULT_OK -> {
                data?.let {
                    val place = Autocomplete.getPlaceFromIntent(data)
                    Log.i(TAG, "Place: ${place.name}, ${place.id}")
                }
            }
            AutocompleteActivity.RESULT_ERROR -> {
                // TODO: Handle the error.
                data?.let {
                    val status = Autocomplete.getStatusFromIntent(data)
                    Log.i(TAG, status.statusMessage)
                }
            }
            Activity.RESULT_CANCELED -> {
                // The user canceled the operation.
            }
        }
        return
    }
    super.onActivityResult(requestCode, resultCode, data)
}
      

Get place predictions programmatically

You can create a custom search UI as an alternative to the UI provided by the autocomplete widget. To do this, your app must get place predictions programmatically. Your app can get a list of predicted place names and/or addresses from the autocomplete API by calling PlacesClient.findAutocompletePredictions(), passing a FindAutocompletePredictionsRequest object with the following parameters:

  • Required: A query string containing the text typed by the user.
  • Recommended: A AutocompleteSessionToken, which groups the query and selection phases of a user search into a discrete session for billing purposes. The session begins when the user starts typing a query, and concludes when they select a place.
  • Recommended: A RectangularBounds object, which specifies latitude and longitude bounds to constrain results to the specified region.
  • Optional: One or more two-letter country codes (ISO 3166-1 Alpha-2), indicating the country or countries to which results should be restricted.
  • Optional: A TypeFilter, which you can use to restrict the results to the specified place type. The following place types are supported:

    • TypeFilter.GEOCODE – Returns only geocoding results, rather than businesses. Use this request to disambiguate results where the specified location may be indeterminate.
    • TypeFilter.ADDRESS – Returns only autocomplete results with a precise address. Use this type when you know the user is looking for a fully specified address.
    • TypeFilter.ESTABLISHMENT – Returns only places that are businesses.
    • TypeFilter.REGIONS – Returns only places that match one of the following types:

      • LOCALITY
      • SUBLOCALITY
      • POSTAL_CODE
      • COUNTRY
      • ADMINISTRATIVE_AREA_LEVEL_1
      • ADMINISTRATIVE_AREA_LEVEL_2
    • TypeFilter.CITIES – Returns only results matching LOCALITY or ADMINISTRATIVE_AREA_LEVEL_3.

  • Optional: A LatLng specifying the location of origin for the request. When you call setOrigin(), the service returns distance in meters (distanceMeters) from the specified origin, for each autocomplete prediction in the response.

For information about place types, see the guide to place types.

The example below shows a complete call to PlacesClient.findAutocompletePredictions().

Java

    // Create a new token for the autocomplete session. Pass this to FindAutocompletePredictionsRequest,
    // and once again when the user makes a selection (for example when calling fetchPlace()).
    AutocompleteSessionToken token = AutocompleteSessionToken.newInstance();

    // Create a RectangularBounds object.
    RectangularBounds bounds = RectangularBounds.newInstance(
        new LatLng(-33.880490, 151.184363),
        new LatLng(-33.858754, 151.229596));
    // Use the builder to create a FindAutocompletePredictionsRequest.
    FindAutocompletePredictionsRequest request = FindAutocompletePredictionsRequest.builder()
        // Call either setLocationBias() OR setLocationRestriction().
        .setLocationBias(bounds)
        //.setLocationRestriction(bounds)
        .setOrigin(new LatLng(-33.8749937,151.2041382))
        .setCountries("AU", "NZ")
        .setTypeFilter(TypeFilter.ADDRESS)
        .setSessionToken(token)
        .setQuery(query)
        .build();

    placesClient.findAutocompletePredictions(request).addOnSuccessListener((response) -> {
        for (AutocompletePrediction prediction : response.getAutocompletePredictions()) {
            Log.i(TAG, prediction.getPlaceId());
            Log.i(TAG, prediction.getPrimaryText(null).toString());
        }
    }).addOnFailureListener((exception) -> {
        if (exception instanceof ApiException) {
            ApiException apiException = (ApiException) exception;
            Log.e(TAG, "Place not found: " + apiException.getStatusCode());
        }
    });
      

Kotlin

    // Create a new token for the autocomplete session. Pass this to FindAutocompletePredictionsRequest,
    // and once again when the user makes a selection (for example when calling fetchPlace()).
    val token = AutocompleteSessionToken.newInstance()

    // Create a RectangularBounds object.
    val bounds = RectangularBounds.newInstance(
        LatLng(-33.880490, 151.184363),
        LatLng(-33.858754, 151.229596)
    )
    // Use the builder to create a FindAutocompletePredictionsRequest.
    val request =
        FindAutocompletePredictionsRequest.builder()
            // Call either setLocationBias() OR setLocationRestriction().
            .setLocationBias(bounds)
            //.setLocationRestriction(bounds)
            .setOrigin(LatLng(-33.8749937, 151.2041382))
            .setCountries("AU", "NZ")
            .setTypeFilter(TypeFilter.ADDRESS)
            .setSessionToken(token)
            .setQuery(query)
            .build()
    placesClient.findAutocompletePredictions(request)
        .addOnSuccessListener { response: FindAutocompletePredictionsResponse ->
            for (prediction in response.autocompletePredictions) {
                Log.i(TAG, prediction.placeId)
                Log.i(TAG, prediction.getPrimaryText(null).toString())
            }
        }.addOnFailureListener { exception: Exception? ->
            if (exception is ApiException) {
                Log.e(TAG, "Place not found: " + exception.statusCode)
            }
        }
      

The API returns an FindAutocompletePredictionsResponse in a Task. The FindAutocompletePredictionsResponse contains a list of AutocompletePrediction objects representing predicted places. The list may be empty, if there is no known place corresponding to the query and the filter criteria.

For each predicted place, you can call the following methods to retrieve place details:

  • getFullText(CharacterStyle) returns the full text of a place description. This is a combination of the primary and secondary text. Example: "Eiffel Tower, Avenue Anatole France, Paris, France". In addition, this method lets you highlight the sections of the description that match the search with a style of your choice, using CharacterStyle. The CharacterStyle parameter is optional. Set it to null if you don't need any highlighting.
  • getPrimaryText(CharacterStyle) returns the main text describing a place. This is usually the name of the place. Examples: "Eiffel Tower", and "123 Pitt Street".
  • getSecondaryText(CharacterStyle) returns the subsidiary text of a place description. This is useful, for example, as a second line when showing autocomplete predictions. Examples: "Avenue Anatole France, Paris, France", and "Sydney, New South Wales".
  • getPlaceId() returns the place ID of the predicted place. A place ID is a textual identifier that uniquely identifies a place, which you can use to retrieve the Place object again later. For more information about place IDs in Places SDK for Android, see the Place Details. For general information about place IDs, see the Place ID overview.
  • getPlaceTypes() returns the list of place types associated with this place.
  • getDistanceMeters() returns the straight-line distance in meters between this place and the origin specified in the request.

Session tokens

Session tokens group the query and selection phases of a user autocomplete search into a discrete session for billing purposes. The session begins when the user starts typing a query, and concludes when they select a place. Each session can have multiple queries, followed by one place selection. Once a session has concluded, the token is no longer valid; your app must generate a fresh token for each session. We recommend using session tokens for all programmatic autocomplete sessions (when you embed a fragment, or launch autocomplete using an intent, the API takes care of this automatically).

The Places SDK for Android uses a AutocompleteSessionToken to identify each session. Your app should pass a new session token upon beginning each new session, then pass that same token, along with a Place ID, in the subsequent call to fetchPlace() to retrieve Place Details for the place that was selected by the user.

Learn more about session tokens.

Constrain autocomplete results

You can constrain autocomplete results to a specific geographic region, and/or filter the results to one or more place types, or to up to five countries. You can apply these constraints to the autocomplete activity, AutocompleteSupportFragment, and programmatic autocomplete APIs.

To constrain results, do the following:

  • To prefer results within the defined region, call setLocationBias() (some results from outside the defined region may still be returned).
  • To only show results within the defined region, call setLocationRestriction() (only results within the defined region will be returned).
  • To return only results that conform to a particular place type, call setTypeFilter() (for example, specifying TypeFilter.ADDRESS will return only results with a precise address).
  • To return only results within up to five specified countries, call setCountries(). Countries must be passed as a two-character, ISO 3166-1 Alpha-2 compatible country code.

Bias results to a specific region

To bias autocomplete results to a specific geographic region, call setLocationBias(), passing a RectangularBounds. The following code example shows calling setLocationBias() on a fragment instance to bias its autocomplete suggestions to a region of Sydney, Australia.

Java

    autocompleteFragment.setLocationBias(RectangularBounds.newInstance(
        new LatLng(-33.880490, 151.184363),
        new LatLng(-33.858754, 151.229596)));
      

Kotlin

    autocompleteFragment.setLocationBias(
        RectangularBounds.newInstance(
            LatLng(-33.880490, 151.184363),
            LatLng(-33.858754, 151.229596)
        )
    )
      

Restrict results to a specific region

To restrict autocomplete results to a specific geographic region, call setLocationRestriction(), passing a RectangularBounds. The following code example shows calling setLocationRestriction() on a fragment instance to bias its autocomplete suggestions to a region of Sydney, Australia.

Java

    autocompleteFragment.setLocationRestriction(RectangularBounds.newInstance(
        new LatLng(-33.880490, 151.184363),
        new LatLng(-33.858754, 151.229596)));
      

Kotlin

    autocompleteFragment.setLocationRestriction(
        RectangularBounds.newInstance(
            LatLng(-33.880490, 151.184363),
            LatLng(-33.858754, 151.229596)
        )
    )
      

Filter results by place type

You can restrict results from an autocomplete request so they only return a certain place type. If the results aren’t restricted, all types are returned. In general only a single type is allowed. The exception is that you can safely mix the GEOCODE and ESTABLISHMENT types; however, this has the same effect as specifying no types.

To filter autocomplete results to a specific place type, call setTypeFilter() to set the filter to use. Then, pass the filter to a fragment or intent.

The following code example shows calling setTypeFilter() on an AutocompleteSupportFragment to set a filter returning only results with a precise address.

Java

    autocompleteFragment.setTypeFilter(TypeFilter.ADDRESS);
      

Kotlin

    autocompleteFragment.setTypeFilter(TypeFilter.ADDRESS)
      

The following code example shows calling setTypeFilter() on an IntentBuilder to set a filter returning only results with a precise address.

Java

    Intent intent = new Autocomplete.IntentBuilder(
        AutocompleteActivityMode.FULLSCREEN, fields)
        .setTypeFilter(TypeFilter.ADDRESS)
        .build(this);
    startActivityForResult(intent, AUTOCOMPLETE_REQUEST_CODE);
      

Kotlin

    val intent = Autocomplete.IntentBuilder(AutocompleteActivityMode.FULLSCREEN, fields)
        .setTypeFilter(TypeFilter.ADDRESS)
        .build(this)
    startActivityForResult(intent, AUTOCOMPLETE_REQUEST_CODE)
      

For information about place types, see the guide to place types.

Filter results by country

To filter autocomplete results to up to five countries, call setCountries() to set the country code. Then, pass the filter to a fragment or intent. Countries must be passed as a two-character, ISO 3166-1 Alpha-2 compatible country code.

The following code example shows calling setCountries() on an AutocompleteSupportFragment, to set a filter returning only results within the specified countries.

Java

    autocompleteFragment.setCountries("AU", "NZ");
      

Kotlin

    autocompleteFragment.setCountries("AU", "NZ")
      

Usage limits

Your usage of the Places API, including the Places SDK for Android, is no longer limited to a maximum number of requests per day (QPD). However, the following usage limits still apply:

  • Rate limit is 100 requests per second (QPS). It is calculated as the sum of client-side and server-side requests for all applications using the credentials of the same project.

Display attributions in your app

  • If your app uses the autocomplete service programmatically, your UI must either display a 'Powered by Google' attribution, or appear within a Google-branded map.
  • If your app uses the autocomplete widget no additional action is required (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 too.

For more details, see the documentation on attributions.

Troubleshooting

Although a wide variety of errors can occur, the majority of the errors your app is likely to experience are usually caused by configuration errors (for example, the wrong API key was used, or the API key was configured incorrectly), or quota errors (your app has exceeded its quota). See Usage Limits for more information about quotas.

Errors that occur in the use of the autocomplete controls are returned in the onActivityResult() callback. Call Autocomplete.getStatus() to get the status message for the result.