Eseguire la migrazione al client SDK New Places

Mantieni tutto organizzato con le raccolte Salva e classifica i contenuti in base alle tue preferenze.

Questa guida spiega le modifiche tra la libreria di compatibilità Places e la nuova versione autonoma dell'SDK Places per Android. Se hai utilizzato la libreria di compatibilità di Places invece di eseguire la migrazione alla nuova versione autonoma di Places SDK per Android, questa guida ti mostra come aggiornare i tuoi progetti in modo da utilizzare la nuova versione di Places SDK per Android.

L'unico modo per accedere alle funzionalità e alle correzioni di bug nell'SDK Places per Android sulla versione 2.6.0 è utilizzare l'SDK Places per Android. Google consiglia di eseguire l'aggiornamento dalla libreria di compatibilità alla nuova versione di Places per Android nel più breve tempo possibile.

Che cosa è cambiato?

Le principali aree di cambiamento sono le seguenti:

  • La nuova versione dell'SDK Places per Android viene distribuita come libreria client statica. Prima di gennaio 2019, l'SDK Places per Android era stato reso disponibile tramite Google Play Services. Da allora, è stata fornita una libreria di compatibilità Places per facilitare la transizione al nuovo SDK Places per Android.
  • Esistono metodi completamente nuovi.
  • Le maschere da campo sono ora supportate per i metodi che restituiscono dettagli sui luoghi. Puoi utilizzare le maschere di campo per specificare i tipi di dati sui luoghi da restituire.
  • I codici di stato utilizzati per segnalare errori sono stati migliorati.
  • Il completamento automatico ora supporta i token di sessione.
  • Il selettore di luoghi non è più disponibile.

Informazioni sulla libreria di compatibilità di Places

A gennaio 2019, con la release 1.0 dell'SDK Places per Android autonomo, Google ha fornito una libreria di compatibilità per agevolare la migrazione dalla versione di Google Play Services ritirata per l'SDK Places per Android (com.google.android.gms:play-services-places).

È stata fornita temporaneamente questa libreria di compatibilità per reindirizzare e tradurre le chiamate API mirate alla versione di Google Play Services alla nuova versione autonoma finché gli sviluppatori non hanno potuto eseguire la migrazione del loro codice per utilizzare i nuovi nomi nell'SDK autonomo. Per ciascuna versione dell'SDK Places per Android rilasciata dalla versione 1.0 alla versione 2.6.0, è stata rilasciata una versione corrispondente della libreria di compatibilità Places per offrire funzionalità equivalenti.

Blocco e ritiro della libreria di compatibilità di Places

Tutte le versioni della libreria di compatibilità per l'SDK Places per Android sono state ritirate a partire dal 31 marzo 2022. La versione 2.6.0 è l'ultima versione della libreria di compatibilità di Places. L'unico modo per accedere alle funzionalità e alle correzioni di bug nell'SDK Places per Android sopra la versione 2.6.0 è utilizzare l'SDK Places per Android.

Google consiglia di eseguire la migrazione all'SDK Places per Android per accedere a nuove funzionalità e correzioni di bug critiche per le release successive alla versione 2.6.0. Se al momento utilizzi la libreria di compatibilità, segui i passaggi riportati nella sezione Installare l'SDK Places per Android per eseguire la migrazione all'SDK Places per Android.

Installa la libreria client

La nuova versione dell'SDK Places per Android viene distribuita come libreria client statica.

Utilizza Maven per aggiungere l'SDK Places per Android al tuo progetto Android Studio:

  1. Se attualmente utilizzi la libreria di compatibilità di Places:

    1. Sostituisci la seguente riga nella sezione dependencies:

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

      Con questa riga per passare all'SDK Places per Android:

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

  2. Se attualmente utilizzi la versione di Play Services dell'SDK Places per Android:

    1. Sostituisci la seguente riga nella sezione dependencies:

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

      Con questa riga per passare all'SDK Places per Android:

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

  3. Sincronizza il tuo progetto Gradle.

  4. Imposta minSdkVersion per il progetto dell'applicazione su 16 o superiore.

  5. Aggiorna gli asset "Powered by 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
    
  6. Crea la tua app. Se noti errori della build dovuti alla conversione all'SDK Places per Android, consulta le sezioni seguenti per informazioni su come risolvere questi errori.

Inizializza il nuovo client Places SDK

Inizializza il nuovo client SDK Places, come illustrato nell'esempio seguente:

// 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);

Codici di stato

Il codice di stato per gli errori del limite QPS è stato modificato. Gli errori relativi al limite di QPS vengono ora restituiti tramite PlaceStatusCodes.OVER_QUERY_LIMIT. Non sono presenti altri limiti QPD.

Sono stati aggiunti i seguenti codici di stato:

  • REQUEST_DENIED: la richiesta è stata rifiutata. Di seguito sono elencati alcuni possibili motivi:

    • Nessuna chiave API fornita.
    • È stata fornita una chiave API non valida.
    • L'API Places non è stata attivata nella console Cloud.
    • È stata fornita una chiave API con restrizioni delle chiavi errate.
  • INVALID_REQUEST: la richiesta non è valida a causa di un argomento mancante o non valido.

  • NOT_FOUND: nessun risultato trovato per la richiesta specificata.

Nuovi metodi

La nuova versione dell'SDK Places per Android introduce metodi completamente nuovi, progettati per la coerenza. Tutti i nuovi metodi aderiscono a quanto segue:

  • Gli endpoint non utilizzano più il verbo get.
  • Gli oggetti richiesta e risposta condividono lo stesso nome del metodo client corrispondente.
  • Gli oggetti di richiesta hanno ora builder; i parametri obbligatori vengono passati come parametri del generatore di richieste.
  • I buffer non vengono più utilizzati.

Questa sezione introduce i nuovi metodi e ne mostra il funzionamento.

Recuperare un luogo in base all'ID

Utilizza fetchPlace() per visualizzare i dettagli di un luogo specifico. fetchPlace() funziona in modo simile a getPlaceById().

Per recuperare un luogo, procedi nel seguente modo:

  1. Richiama fetchPlace(), trasmettendo un oggetto FetchPlaceRequest che specifica un ID luogo e un elenco di campi che specificano i dati sul luogo da restituire.

    // 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. Chiama addOnSuccessListener() per gestire FetchPlaceResponse. Viene restituito un singolo risultato di Place.

    // 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());
        }
    });
    

Recuperare una foto del luogo

Usa fetchPhoto() per ottenere una foto del luogo. fetchPhoto() restituisce le foto di un luogo. Il pattern per richiedere una foto è stato semplificato. Ora puoi richiedere PhotoMetadata direttamente dall'oggetto Place; non è più necessaria una richiesta separata. Le foto possono avere una larghezza o un'altezza massima di 1600 px. fetchPhoto() funziona in modo simile a getPhoto().

Per recuperare le foto dei luoghi:

  1. Imposta una chiamata a fetchPlace(). Assicurati di includere il campo PHOTO_METADATAS nella tua richiesta:

    List<Place.Field> fields = Arrays.asList(Place.Field.PHOTO_METADATAS);
    
  2. Ottieni un oggetto Luogo (in questo esempio viene utilizzato fetchPlace(), ma puoi anche utilizzare findCurrentPlace()):

    FetchPlaceRequest placeRequest = FetchPlaceRequest.builder(placeId, fields).build();
    
  3. Aggiungi un elemento OnSuccessListener per recuperare i metadati della foto dall'elemento Place risultante in FetchPlaceResponse, quindi utilizza i metadati della foto generati per ottenere una bitmap e un testo di attribuzione:

    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());
            }
        });
    });
    

Trova un luogo in base alla località dell'utente

Utilizza findCurrentPlace() per trovare la posizione corrente del dispositivo dell'utente. findCurrentPlace() restituisce un elenco di PlaceLikelihood che indicano i luoghi in cui è più probabile si trovi il dispositivo dell'utente. findCurrentPlace() funziona in modo simile a getCurrentPlace().

Segui questi passaggi per trovare la posizione attuale del dispositivo dell'utente:

  1. Assicurati che la tua app richieda le autorizzazioni ACCESS_FINE_LOCATION e ACCESS_WIFI_STATE. L'utente deve concedere l'autorizzazione per accedere alla posizione attuale del suo dispositivo. Per ulteriori dettagli, consulta Richiedere le autorizzazioni delle app.

  2. Creare un FindCurrentPlaceRequest, incluso un elenco di tipi di dati relativi al luogo da restituire.

      // 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. Richiama FindCurrentPlace e gestisci la risposta, verificando innanzitutto che l'utente abbia concesso l'autorizzazione a utilizzare la posizione del suo 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();
      }
    

Trovare le previsioni di completamento automatico

Utilizza findAutocompletePredictions() per restituire previsioni di luoghi in risposta alle query di ricerca degli utenti. findAutocompletePredictions() funziona in modo simile a getAutocompletePredictions().

L'esempio seguente mostra come chiamare 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());
   }
});

Token di sessione

I token di sessione raggruppano le fasi di query e selezione di una ricerca utente in una sessione separata ai fini della fatturazione. Ti consigliamo di utilizzare i token di sessione per tutte le sessioni di completamento automatico. La sessione inizia quando l'utente inizia a digitare una query e termina quando seleziona un luogo. Ogni sessione può avere più query, seguite da una selezione di un luogo. Al termine di una sessione, il token non è più valido. L'app deve generare un token aggiornato per ogni sessione.

Mascherine da campo

Nei metodi che restituiscono dettagli sul luogo, devi specificare i tipi di dati sul luogo da restituire per ogni richiesta. In questo modo puoi avere la certezza di richiedere (e pagare) solo i dati effettivamente utilizzati.

Per specificare i tipi di dati da restituire, passa un array di Place.Field in FetchPlaceRequest, come mostrato nell'esempio seguente:

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

Puoi utilizzare uno o più dei seguenti campi:

  • 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

Scopri di più sugli SKU di dati di Places.

Aggiornamenti del selettore dei luoghi e del completamento automatico

Questa sezione spiega le modifiche ai widget Places (Selettore luogo e Completamento automatico).

Completamento automatico di pubblicità programmatica

Sono state apportate le seguenti modifiche al completamento automatico:

  • PlaceAutocomplete è stato rinominato in Autocomplete.
    • PlaceAutocomplete.getPlace è stato rinominato in Autocomplete.getPlaceFromIntent.
    • PlaceAutocomplete.getStatus è stato rinominato in Autocomplete.getStatusFromIntent.
  • PlaceAutocomplete.RESULT_ERROR è stato rinominato in AutocompleteActivity.RESULT_ERROR (la gestione degli errori per il frammento di completamento automatico NON è cambiata).

Selettore luogo

Il selettore di luoghi è stato ritirato il 29 gennaio 2019. È stata disattivata il 29 luglio 2019 e non è più disponibile. L'uso continuato genera un messaggio di errore. Il nuovo SDK non supporta il selettore di luoghi.

Widget con completamento automatico

I widget del completamento automatico sono stati aggiornati:

  • Il prefisso Place è stato rimosso da tutti i corsi.
  • Aggiunto il supporto per i token di sessione. Il widget gestisce automaticamente i token in background.
  • Aggiunta del supporto per le maschere di campo, che consentono di scegliere i tipi di dati di luogo da restituire dopo che l'utente effettua una selezione.

Le sezioni seguenti mostrano come aggiungere un widget di completamento automatico al tuo progetto.

Incorpora AutocompleteFragment

Per aggiungere un frammento di completamento automatico, procedi nel seguente modo:

  1. Aggiungi un frammento al layout XML della tua attività, come mostrato nell'esempio seguente.

    <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. Per aggiungere il widget di completamento automatico all'attività, procedi nel seguente modo:

    • Inizializza Places, passando il contesto dell'applicazione e la chiave API.
    • Inizializza AutocompleteSupportFragment.
    • Richiama setPlaceFields() per indicare i tipi di dati relativi al luogo che vuoi ricevere.
    • Aggiungi PlaceSelectionListener per eseguire una determinata operazione con il risultato, nonché per gestire eventuali errori che potrebbero verificarsi.

    L'esempio seguente mostra l'aggiunta di un widget di completamento automatico a un'attività:

    /**
     * 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);
        }
    });
    

Utilizza un intent per avviare l'attività di completamento automatico

  1. Inizializza Places, trasmettendo il contesto dell'app e la tua chiave API
  2. Usa Autocomplete.IntentBuilder per creare un intent, passando la modalità PlaceAutocomplete che ti interessa (schermo intero o overlay). L'intent deve chiamare startActivityForResult, trasmettendo un codice di richiesta che identifica l'intent.
  3. Sostituisci il callback onActivityResult per ricevere il luogo selezionato.

L'esempio seguente mostra come utilizzare un intent per avviare il completamento automatico e gestire il risultato:

    /**
     * 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.
            }
        }
    }

Selettore di luogo non più disponibile

Il selettore di luoghi è stato ritirato il 29 gennaio 2019. È stata disattivata il 29 luglio 2019 e non è più disponibile. L'uso continuato genera un messaggio di errore. Il nuovo SDK non supporta il selettore di luoghi.