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.
- Há 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:
Se você usa a biblioteca de compatibilidade do Places:
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'
Se você usa a versão do Google Play Services do SDK do Places para Android:
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'
Sincronize seu projeto do Gradle.
Defina o
minSdkVersion
do projeto do aplicativo como 16 ou mais recente.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
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:
Chame
fetchPlace()
, transmitindo um objetoFetchPlaceRequest
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();
Chame
addOnSuccessListener()
para gerenciar oFetchPlaceResponse
. Um únicoPlace
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:
Faça uma chamada para
fetchPlace()
. Inclua o parâmetroPHOTO_METADATAS
na sua solicitação:List<Place.Field> fields = Arrays.asList(Place.Field.PHOTO_METADATAS);
Receba um objeto Place. Este exemplo usa
fetchPlace()
, mas também é possível usarfindCurrentPlace()
):FetchPlaceRequest placeRequest = FetchPlaceRequest.builder(placeId, fields).build();
Adicione uma
OnSuccessListener
para receber os metadados de foto do resultadoPlace
naFetchPlaceResponse
, 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 PlaceLikelihood
s 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:
Verifique se o app solicita os
ACCESS_FINE_LOCATION
eACCESS_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.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();
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.Field
s 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 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. 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:
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" />
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); } });
- Inicialize
Usar uma intent para iniciar a atividade de preenchimento automático
- Inicialize
Places
, transmitindo o contexto do app e sua chave de API - Use
Autocomplete.IntentBuilder
para criar uma intent, transmitindo a mensagem ModoPlaceAutocomplete
(tela cheia ou sobreposição). A intent precisa chamarstartActivityForResult
, transmitindo um código de solicitação que identifica seu intenção. - 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.