Como migrar para o novo cliente do SDK do Places

Neste guia, explicamos as mudanças entre a guia biblioteca de compatibilidade e a nova versão autônoma da SDK do Places para Android. Se você estiver usando a biblioteca de compatibilidade do Places em vez de migrar para o a nova versão independente do SDK do Places para Android, este guia mostra como atualizar seus projetos para usar a nova versão do SDK do Places para Android.

A única maneira de acessar os recursos e as correções de bugs no SDK do Places para Android versão 2.6.0 e posteriores é usar o SDK do Places para Android. O Google recomenda atualizar da biblioteca de compatibilidade para a nova SDK do Places para Android assim que possível.

O que mudou?

As principais áreas de mudança são as seguintes:

  • A nova versão do SDK do Places para Android foi distribuída como uma biblioteca de cliente estática. Antes de janeiro de 2019, o SDK do Places para Android foi disponibilizado pelo Google Play Services. Desde então, uma conta do Places biblioteca de compatibilidade foi fornecida para facilitar a transição para a nova SDK do Places para Android.
  • métodos totalmente novos.
  • As máscaras de campo agora são compatíveis com métodos que retornam o lugar detalhes. Você pode usar máscaras de campo para especificar quais tipos de dados de lugar serão voltar.
  • Os códigos de status usados para informar erros foram aprimorados.
  • O preenchimento automático agora oferece suporte a tokens de sessão.
  • O Place Picker não está mais disponível.

Sobre a biblioteca de compatibilidade do Places

Em janeiro de 2019, com o lançamento da versão 1.0 do SDK independente do Places para Android, O Google forneceu uma biblioteca de compatibilidade para ajudar na migração da versão desativada do Google Play Services do SDK do Places para Android (com.google.android.gms:play-services-places).

Esta biblioteca de compatibilidade foi fornecida temporariamente para redirecionar e traduzir Chamadas de API destinadas à versão do Google Play Services para a nova versão até que os desenvolvedores possam migrar o código para usar os novos nomes na SDK autônomo. Para cada versão do SDK do Places para Android que foram lançadas da versão 1.0 até a versão 2.6.0, uma versão da biblioteca de compatibilidade do Places foi lançada para fornecer equivalentes funcionalidade de armazenamento.

Como congelar e descontinuar a biblioteca de compatibilidade do Places

Todas as versões da biblioteca de compatibilidade do SDK do Places para Android foram descontinuados em 31 de março de 2022. A versão 2.6.0 é a última versão Biblioteca de compatibilidade do Places. A única maneira de acessar recursos e correções de bugs no Places O SDK para Android posterior à versão 2.6.0 vai usar o SDK do Places para Android.

O Google recomenda migrar para o SDK do Places para Android. para acessar novos recursos e correções de bugs críticos para versões acima da versão 2.6.0. Se você estiver usando a biblioteca de compatibilidade, siga as etapas abaixo na Instale a seção SDK do Places para Android para migrar SDK do Places para Android.

Instale a biblioteca de cliente

A nova versão do SDK do Places para Android é distribuída como um biblioteca de cliente estática.

Use o Maven para adicionar a SDK do Places para Android ao seu projeto do Android Studio:

  1. Se você usa a biblioteca de compatibilidade do Places:

    1. Substitua a linha abaixo na seção dependencies:

          implementation 'com.google.android.libraries.places:places-compat:X.Y.Z'

      Com esta linha para alternar para o SDK do Places para Android:

          implementation 'com.google.android.libraries.places:places:3.3.0'

  2. Se você usa a versão do Google Play Services do SDK do Places para Android:

    1. Substitua a linha abaixo na seção dependencies:

          implementation 'com.google.android.gms:play-services-places:X.Y.Z'

      Com esta linha para alternar para o SDK do Places para Android:

          implementation 'com.google.android.libraries.places:places:3.3.0'

  3. Sincronize seu projeto do Gradle.

  4. Defina o minSdkVersion do projeto do aplicativo como 16 ou mais recente.

  5. Atualize o painel "Powered by Google" recursos:

    @drawable/powered_by_google_light // OLD
    @drawable/places_powered_by_google_light // NEW
    @drawable/powered_by_google_dark // OLD
    @drawable/places_powered_by_google_dark // NEW
    
  6. Crie o app. Se houver erros de build devido à conversão para o SDK do Places para Android, consulte as seções abaixo. para resolver esses erros.

Inicializar o novo cliente do SDK do Places

Inicialize o novo cliente do SDK do Places como mostrado no exemplo a seguir:

// Add an import statement for the client library.
import com.google.android.libraries.places.api.Places;

...

// Initialize Places.
Places.initialize(getApplicationContext(), apiKey);

// Create a new Places client instance.
PlacesClient placesClient = Places.createClient(this);

Códigos de status

O código de status dos erros de limite de QPS foi alterado. Os erros de limite de QPS agora são retornado por PlaceStatusCodes.OVER_QUERY_LIMIT. Não há mais limites de QPD.

Os seguintes códigos de status foram adicionados:

  • REQUEST_DENIED: a solicitação foi negada. Alguns possíveis motivos para isso:

    • Nenhuma chave de API foi fornecida.
    • Uma chave de API inválida foi fornecida.
    • A API Places não foi ativada no console do Cloud.
    • Uma chave de API foi fornecida com restrições incorretas.
  • INVALID_REQUEST: a solicitação é inválida devido a um valor ausente ou inválido. .

  • NOT_FOUND: nenhum resultado foi encontrado para a solicitação em questão.

Novos métodos

A nova versão do SDK do Places para Android apresenta as novas métodos, que foram projetados para serem consistentes. Todos os novos métodos devem aderir ao seguinte:

  • Os endpoints não usam mais o verbo get.
  • Os objetos de solicitação e resposta compartilham o mesmo nome que o método client.
  • Os objetos de solicitação agora têm builders. os parâmetros obrigatórios são transmitidos como solicitação parâmetros do builder.
  • Os buffers não são mais usados.

Esta seção apresenta os novos métodos e mostra como eles funcionam.

Buscar um lugar por ID

Usar fetchPlace() para conferir detalhes sobre um lugar específico. fetchPlace() funciona de forma semelhante a getPlaceById().

Siga estas etapas para buscar um lugar:

  1. Chame fetchPlace(), transmitindo um objeto FetchPlaceRequest especificando um Place. ID e uma lista de campos especificando os dados do lugar a serem retornados.

    // Define a Place ID.
    String placeId = "INSERT_PLACE_ID_HERE";
    
    // Specify the fields to return.
    List<Place.Field> placeFields = Arrays.asList(Place.Field.ID, Place.Field.NAME);
    
    // Construct a request object, passing the place ID and fields array.
    FetchPlaceRequest request = FetchPlaceRequest.builder(placeId, placeFields)
            .build();
    
    
  2. Chame addOnSuccessListener() para gerenciar o FetchPlaceResponse. Um único Place resultado é retornado.

    // Add a listener to handle the response.
    placesClient.fetchPlace(request).addOnSuccessListener((response) -> {
      Place place = response.getPlace();
      Log.i(TAG, "Place found: " + place.getName());
    }).addOnFailureListener((exception) -> {
        if (exception instanceof ApiException) {
            ApiException apiException = (ApiException) exception;
            int statusCode = apiException.getStatusCode();
            // Handle error with given status code.
            Log.e(TAG, "Place not found: " + exception.getMessage());
        }
    });
    

Buscar uma foto de lugar

Usar fetchPhoto() para obter uma foto do lugar. fetchPhoto() retorna fotos de um lugar. O padrão para solicitar uma foto foi simplificada. Agora você pode solicitar PhotoMetadata diretamente do objeto Place. uma solicitação separada não é mais necessária. As fotos podem ter largura ou altura máxima de 1.600 px. fetchPhoto() função semelhante a getPhoto().

Siga estas etapas para buscar fotos de lugares:

  1. Faça uma chamada para fetchPlace(). Inclua o parâmetro PHOTO_METADATAS na sua solicitação:

    List<Place.Field> fields = Arrays.asList(Place.Field.PHOTO_METADATAS);
    
  2. Receba um objeto Place. Este exemplo usa fetchPlace(), mas também é possível usar findCurrentPlace()):

    FetchPlaceRequest placeRequest = FetchPlaceRequest.builder(placeId, fields).build();
    
  3. Adicione uma OnSuccessListener para receber os metadados de foto do resultado Place na FetchPlaceResponse, depois use os metadados de foto resultantes para receber um bitmap e um texto de atribuição:

    placesClient.fetchPlace(placeRequest).addOnSuccessListener((response) -> {
        Place place = response.getPlace();
    
        // Get the photo metadata.
        PhotoMetadata photoMetadata = place.getPhotoMetadatas().get(0);
    
        // Get the attribution text.
        String attributions = photoMetadata.getAttributions();
    
        // Create a FetchPhotoRequest.
        FetchPhotoRequest photoRequest = FetchPhotoRequest.builder(photoMetadata)
                .setMaxWidth(500) // Optional.
                .setMaxHeight(300) // Optional.
                .build();
        placesClient.fetchPhoto(photoRequest).addOnSuccessListener((fetchPhotoResponse) -> {
            Bitmap bitmap = fetchPhotoResponse.getBitmap();
            imageView.setImageBitmap(bitmap);
        }).addOnFailureListener((exception) -> {
            if (exception instanceof ApiException) {
                ApiException apiException = (ApiException) exception;
                int statusCode = apiException.getStatusCode();
                // Handle error with given status code.
                Log.e(TAG, "Place not found: " + exception.getMessage());
            }
        });
    });
    

Encontrar um lugar a partir do local do usuário

Usar findCurrentPlace() para encontrar a localização atual do dispositivo do usuário. findCurrentPlace() retorna uma lista de PlaceLikelihoods indicando locais em que o dispositivo do usuário é mais provável de estar localizado. findCurrentPlace() funciona de forma semelhante a getCurrentPlace().

Siga estas etapas para saber a localização atual do dispositivo do usuário:

  1. Verifique se o app solicita os ACCESS_FINE_LOCATION e ACCESS_WIFI_STATE. O usuário precisa conceder permissão para acessar o a localização atual do dispositivo. Consulte Solicitar aplicativo Permissões para detalhes.

  2. Crie um FindCurrentPlaceRequest, incluindo uma lista de tipos de dados de lugar para os quais voltar.

      // Use fields to define the data types to return.
      List<Place.Field> placeFields = Arrays.asList(Place.Field.NAME);
    
      // Use the builder to create a FindCurrentPlaceRequest.
      FindCurrentPlaceRequest request =
              FindCurrentPlaceRequest.builder(placeFields).build();
    
  3. Chame findCurrentPlace e processe a resposta, verificando primeiro se o usuário concedeu permissão para usar a localização do dispositivo.

      // Call findCurrentPlace and handle the response (first check that the user has granted permission).
      if (ContextCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
          placesClient.findCurrentPlace(request).addOnSuccessListener(((response) -> {
              for (PlaceLikelihood placeLikelihood : response.getPlaceLikelihoods()) {
                  Log.i(TAG, String.format("Place '%s' has likelihood: %f",
                          placeLikelihood.getPlace().getName(),
                          placeLikelihood.getLikelihood()));
                  textView.append(String.format("Place '%s' has likelihood: %f\n",
                          placeLikelihood.getPlace().getName(),
                          placeLikelihood.getLikelihood()));
              }
          })).addOnFailureListener((exception) -> {
              if (exception instanceof ApiException) {
                  ApiException apiException = (ApiException) exception;
                  Log.e(TAG, "Place not found: " + apiException.getStatusCode());
              }
          });
      } else {
          // A local method to request required permissions;
          // See https://developer.android.com/training/permissions/requesting
          getLocationPermission();
      }
    

Encontrar previsões de preenchimento automático

Usar findAutocompletePredictions() para retornar previsões de locais em resposta a consultas de pesquisa do usuário. findAutocompletePredictions() funciona de forma semelhante a getAutocompletePredictions().

O exemplo a seguir mostra como chamar findAutocompletePredictions():

// 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)
   .setCountry("au")
   .setTypesFilter(Arrays.asList(PlaceTypes.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());
   }
});

Tokens de sessão

Os tokens de sessão agrupam as fases de consulta e seleção de uma pesquisa do usuário em um para fins de cobrança. Recomendamos o uso de tokens de sessão em todas as sessões de preenchimento automático. A sessão começa quando o usuário começa a digitar um e termina quando selecionam um local. Cada sessão pode ter várias seguidas por uma seleção de local. Após o término de uma sessão, token não é mais válido. seu aplicativo deve gerar um novo token para cada sessão.

Máscaras de campo

Nos métodos que retornam detalhes do lugar, é necessário especificar os tipos de lugar. dados sejam retornados com cada solicitação. Isso ajuda a garantir que você solicite apenas (e pagar) pelos dados que você realmente vai usar.

Para especificar quais tipos de dados retornar, transmita uma matriz de Place.Fields na sua FetchPlaceRequest, conforme mostrado no exemplo a seguir:

// Include address, ID, and phone number.
List<Place.Field> placeFields = Arrays.asList(Place.Field.ADDRESS,
                                              Place.Field.ID,
                                              Place.Field.PHONE_NUMBER);

Você pode usar um ou mais dos seguintes campos:

  • Place.Field.ADDRESS
  • Place.Field.ID
  • Place.Field.LAT_LNG
  • Place.Field.NAME
  • Place.Field.OPENING_HOURS
  • Place.Field.PHONE_NUMBER
  • Place.Field.PHOTO_METADATAS
  • Place.Field.PLUS_CODE
  • Place.Field.PRICE_LEVEL
  • Place.Field.RATING
  • Place.Field.TYPES
  • Place.Field.USER_RATINGS_TOTAL
  • Place.Field.VIEWPORT
  • Place.Field.WEBSITE_URI

Leia mais sobre as SKUs de dados do Places.

Atualizações do Place Picker e Autocomplete

Esta seção explica as alterações nos widgets Lugares (Seletor de local e preenchimento automático).

Preenchimento automático programático

As seguintes mudanças foram feitas no preenchimento automático:

  • PlaceAutocomplete foi renomeado como Autocomplete.
    • PlaceAutocomplete.getPlace foi renomeado como Autocomplete.getPlaceFromIntent.
    • PlaceAutocomplete.getStatus foi renomeado como Autocomplete.getStatusFromIntent.
  • PlaceAutocomplete.RESULT_ERROR foi renomeado como AutocompleteActivity.RESULT_ERROR. (o tratamento de erros do fragmento de preenchimento automático NÃO mudou).

Seletor de local

O Place Picker foi descontinuado em 29 de janeiro de 2019. Ligado em 29 de julho de 2019. Ela não está mais disponível. O uso contínuo resultará em uma mensagem de erro. O novo SDK não é compatível com o Place Picker.

Widgets de preenchimento automático

Os widgets de preenchimento automático foram atualizados:

  • O prefixo Place foi removido de todas as classes.
  • Inclusão de compatibilidade com tokens de sessão. O widget gerencia tokens para você automaticamente em segundo plano.
  • Suporte adicionado para máscaras de campo, que permitem escolher quais tipos de lugar que os dados sejam retornados depois que o usuário fizer uma seleção.

As seções abaixo mostram como adicionar um widget de preenchimento automático ao projeto.

Incorporar um AutocompleteFragment

Para adicionar um fragmento de preenchimento automático, siga estas etapas:

  1. Adicione um fragmento ao layout XML da atividade, conforme mostrado abaixo exemplo.

    <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"
      />
    
  2. Para adicionar o widget de preenchimento automático à atividade, siga estas etapas:

    • Inicialize Places, transmitindo o contexto do aplicativo e sua chave de API.
    • Inicialize o AutocompleteSupportFragment:
    • Chame setPlaceFields() para indicar os tipos de dados de lugar que você quer conseguir.
    • Adicione uma PlaceSelectionListener para fazer algo com o resultado, assim como e lidar com erros que podem ocorrer.

    O exemplo a seguir mostra como adicionar um widget de preenchimento automático a uma atividade:

    /**
     * Initialize Places. For simplicity, the API key is hard-coded. In a production
     * environment we recommend using a secure mechanism to manage API keys.
     */
    if (!Places.isInitialized()) {
        Places.initialize(getApplicationContext(), "YOUR_API_KEY");
    }
    
    // Initialize the AutocompleteSupportFragment.
    AutocompleteSupportFragment autocompleteFragment = (AutocompleteSupportFragment)
            getSupportFragmentManager().findFragmentById(R.id.autocomplete_fragment);
    
    autocompleteFragment.setPlaceFields(Arrays.asList(Place.Field.ID, Place.Field.NAME));
    
    autocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
        @Override
        public void onPlaceSelected(Place place) {
            // TODO: Get info about the selected place.
            Log.i(TAG, "Place: " + place.getName() + ", " + place.getId());
        }
    
        @Override
        public void onError(Status status) {
            // TODO: Handle the error.
            Log.i(TAG, "An error occurred: " + status);
        }
    });
    

Usar uma intent para iniciar a atividade de preenchimento automático

  1. Inicialize Places, transmitindo o contexto do app e sua chave de API
  2. Use Autocomplete.IntentBuilder para criar uma intent, transmitindo a mensagem Modo PlaceAutocomplete (tela cheia ou sobreposição). A intent precisa chamar startActivityForResult, transmitindo um código de solicitação que identifica seu intenção.
  3. Modifique o callback onActivityResult para receber o lugar selecionado.

O exemplo a seguir mostra como usar uma intent para iniciar o preenchimento automático. e processar o resultado:

    /**
     * Initialize Places. For simplicity, the API key is hard-coded. In a production
     * environment we recommend using a secure mechanism to manage API keys.
     */
    if (!Places.isInitialized()) {
        Places.initialize(getApplicationContext(), "YOUR_API_KEY");
    }

    ...

    // Set the fields to specify which types of place data to return.
    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);

    ...

    /**
     * Override the activity's onActivityResult(), check the request code, and
     * do something with the returned place data (in this example its place name and place ID).
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, 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.
            }
        }
    }

O Seletor de lugar não está mais disponível

O Place Picker foi descontinuado em 29 de janeiro de 2019. Desativado em 29 de julho de 2019. Ela não está mais disponível. O uso contínuo resultará em uma mensagem de erro. O novo SDK não é compatível com o Place Picker.