Este guia explica as mudanças entre a biblioteca de compatibilidade do Places e a nova versão independente do SDK do Places para Android. Se você estiver usando a biblioteca de compatibilidade do Places em vez de migrar para 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 versão do 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 é distribuída como uma biblioteca de cliente estática. Antes de janeiro de 2019, o SDK do Places para Android era disponibilizado pelo Google Play Services. Desde então, uma biblioteca de compatibilidade do Places foi fornecida para facilitar a transição para o novo SDK do Places para Android.
- Há métodos totalmente novos.
- Máscaras de campo agora são compatíveis com métodos que retornam detalhes do lugar. É possível usar máscaras de campo para especificar quais tipos de dados de lugar serão retornados.
- Os códigos de status usados para informar erros foram aprimorados.
- O preenchimento automático agora aceita 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 SDK do Places para Android do Google Play Services (com.google.android.gms:play-services-places
).
Essa 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 independente até que os desenvolvedores pudessem migrar o código para usar os novos nomes no SDK independente. Para cada versão do SDK do Places para Android lançada da versão 1.0 à 2.6.0, uma versão correspondente da biblioteca de compatibilidade do Places foi lançada para oferecer funcionalidade equivalente.
Congelamento e descontinuação da biblioteca de compatibilidade do Places
Todas as versões da biblioteca de compatibilidade do SDK do Places para Android foram descontinuadas em 31 de março de 2022. A versão 2.6.0 é a última versão da biblioteca de compatibilidade do Places. 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 migrar para o SDK do Places para Android para acessar novos recursos e correções de bugs críticas para versões acima da 2.6.0. Se você estiver usando a biblioteca de compatibilidade, siga as etapas abaixo na seção Instalar o SDK do Places para Android para migrar para o SDK do Places para Android.
Instale a biblioteca de cliente
A nova versão do SDK do Places para Android é distribuída como uma biblioteca de cliente estática.
Use o Maven para adicionar o Places SDK para Android ao seu projeto do Android Studio:
Se você estiver usando a biblioteca de compatibilidade do Places:
Substitua a seguinte linha na seção
dependencies
:implementation 'com.google.android.libraries.places:places-compat:X.Y.Z'
Com esta linha para mudar para o SDK do Places para Android:
implementation 'com.google.android.libraries.places:places:3.3.0'
Se você estiver usando a versão do Play Services do SDK do Places para Android:
Substitua a seguinte linha na seção
dependencies
:implementation 'com.google.android.gms:play-services-places:X.Y.Z'
Com esta linha para mudar para o SDK do Places para Android:
implementation 'com.google.android.libraries.places:places:3.3.0'
Sincronize seu projeto do Gradle.
Defina a
minSdkVersion
do projeto do aplicativo como 16 ou mais recente.Atualize os recursos "Com tecnologia do Google":
@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
Crie seu app. Se você encontrar erros de build devido à conversão para o SDK do Places para Android, consulte as seções abaixo para saber como resolver esses erros.
Inicializar o novo cliente do SDK do Places
Inicialize o novo cliente do SDK do Places, conforme 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
retornados 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 argumento ausente ou inválido.NOT_FOUND
: nenhum resultado foi encontrado para a solicitação.
Novos métodos
A nova versão do SDK do Places para Android apresenta métodos totalmente novos, que foram projetados para consistência. Todos os novos métodos atendem aos seguintes requisitos:
- Os endpoints não usam mais o verbo
get
. - Os objetos de solicitação e resposta compartilham o mesmo nome do método do cliente correspondente.
- Os objetos de solicitação agora têm builders. Os parâmetros obrigatórios são transmitidos como parâmetros do builder de solicitação.
- 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
Use fetchPlace()
para conferir detalhes sobre um lugar específico. fetchPlace()
funciona de maneira semelhante a
getPlaceById()
.
Siga estas etapas para buscar um lugar:
Chame
fetchPlace()
, transmitindo um objetoFetchPlaceRequest
que especifique um ID de lugar e uma lista de campos que especifiquem os dados de 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.DISPLAY_NAME); // Construct a request object, passing the place ID and fields array. FetchPlaceRequest request = FetchPlaceRequest.builder(placeId, placeFields) .build();
Chame
addOnSuccessListener()
para processar oFetchPlaceResponse
. Um único resultadoPlace
é 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 um lugar
Use fetchPhoto()
para receber uma foto de um lugar. fetchPhoto()
retorna fotos de um lugar. O padrão
para solicitar uma foto foi simplificado. Agora é possível 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. A função fetchPhoto()
funciona de maneira semelhante à getPhoto()
.
Siga estas etapas para buscar fotos de lugares:
Configure uma chamada para
fetchPlace()
. Inclua o campoPHOTO_METADATAS
na solicitação:List<Place.Field> fields = Arrays.asList(Place.Field.PHOTO_METADATAS);
Receba um objeto Place (este exemplo usa
fetchPlace()
, mas você também pode usarfindCurrentPlace()
):FetchPlaceRequest placeRequest = FetchPlaceRequest.builder(placeId, fields).build();
Adicione um
OnSuccessListener
para receber os metadados da foto doPlace
resultante noFetchPlaceResponse
e use os metadados da 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
Use findCurrentPlace()
para encontrar a localização atual do dispositivo do usuário. findCurrentPlace()
retorna uma lista de PlaceLikelihood
s indicando os lugares onde o dispositivo do usuário
é mais provável que esteja localizado. findCurrentPlace()
funciona de maneira semelhante a
getCurrentPlace()
.
Siga estas etapas para conferir a localização atual do dispositivo do usuário:
Verifique se o app solicita as permissões
ACCESS_FINE_LOCATION
eACCESS_WIFI_STATE
. O usuário precisa conceder permissão para acessar a localização atual do dispositivo. Consulte Solicitar permissões de apps para mais detalhes.Crie um
FindCurrentPlaceRequest
, incluindo uma lista de tipos de dados de lugar a serem retornados.// Use fields to define the data types to return. List<Place.Field> placeFields = Arrays.asList(Place.Field.DISPLAY_NAME); // Use the builder to create a FindCurrentPlaceRequest. FindCurrentPlaceRequest request = FindCurrentPlaceRequest.builder(placeFields).build();
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
Use findAutocompletePredictions()
para retornar previsões de lugares em resposta a consultas de pesquisa do usuário.
findAutocompletePredictions()
funciona de maneira 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 uma sessão discreta para fins de faturamento. Recomendamos o uso de tokens de sessão em todas as sessões de preenchimento automático. A sessão começa quando a pessoa começa a digitar uma consulta e termina quando seleciona um lugar. Cada sessão pode ter várias consultas, seguidas por uma seleção de lugar. Após a conclusão de uma sessão, o token perde a validade. Seu app precisa gerar um novo token para cada sessão.
Máscaras de campo
Em métodos que retornam detalhes do lugar, é necessário especificar quais tipos de dados do lugar serão retornados em cada solicitação. Isso ajuda a garantir que você solicite e pague apenas os dados que vai usar.
Para especificar quais tipos de dados retornar, transmita uma matriz de Place.Field
s no
FetchPlaceRequest
, conforme mostrado no exemplo abaixo:
// Include address, ID, and phone number.
List<Place.Field> placeFields = Arrays.asList(Place.Field.FORMATTED_ADDRESS,
Place.Field.ID,
Place.Field.INTERNATIONAL_PHONE_NUMBER);
Para conferir uma lista de campos que podem ser usados em uma máscara de campo, consulte Campos de dados de lugar (novo) .
Leia mais sobre as SKUs de dados do Places.
Atualizações do Place Picker e do Autocomplete
Esta seção explica as mudanças nos widgets do Places (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 comoAutocomplete
.PlaceAutocomplete.getPlace
foi renomeado comoAutocomplete.getPlaceFromIntent
.PlaceAutocomplete.getStatus
foi renomeado comoAutocomplete.getStatusFromIntent
.
PlaceAutocomplete.RESULT_ERROR
foi renomeado comoAutocompleteActivity.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. Ele foi desativado em 29 de julho de 2019 e não está mais disponível. O uso contínuo resultará em uma mensagem de erro. O novo SDK não oferece suporte ao Place Picker.
Widgets de preenchimento automático
Os widgets de preenchimento automático foram atualizados:
- O prefixo
Place
foi removido de todas as classes. - Adição de suporte a tokens de sessão. O widget gerencia tokens para você automaticamente em segundo plano.
- Foi adicionado suporte a máscaras de campo, que permitem escolher quais tipos de dados de lugar fornecer depois que o usuário faz uma seleção.
As seções a seguir mostram como adicionar um widget de preenchimento automático ao seu projeto.
Incorporar um AutocompleteFragment
Para adicionar um fragmento de preenchimento automático, siga estas etapas:
Adicione um fragmento ao layout XML da atividade, conforme mostrado no exemplo a seguir.
<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" />
Para adicionar o widget de preenchimento automático à atividade, siga estas etapas:
- Inicialize
Places
, transmitindo o contexto do aplicativo e a chave de API. - Inicialize o
AutocompleteSupportFragment
: - Chame
setPlaceFields()
para indicar os tipos de dados de lugar que você quer receber. - Adicione um
PlaceSelectionListener
para fazer algo com o resultado e lidar com os erros que possam ocorrer.
O exemplo abaixo 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.DISPLAY_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); } });
- Inicialize
Usar uma intent para iniciar a atividade de preenchimento automático
- Inicializar
Places
, transmitindo o contexto do app e a chave de API - Use
Autocomplete.IntentBuilder
para criar uma intent, transmitindo o modoPlaceAutocomplete
desejado (tela cheia ou sobreposição). A intent precisa chamarstartActivityForResult
, transmitindo um código de solicitação que identifica a intent. - Substitua 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.DISPLAY_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 Place Picker não está mais disponível
O Place Picker foi descontinuado em 29 de janeiro de 2019. Ele foi desativado em 29 de julho de 2019 e não está mais disponível. O uso contínuo resultará em uma mensagem de erro. O novo SDK não oferece suporte ao Place Picker.