Zum neuen Places SDK Client migrieren

In diesem Leitfaden werden die Änderungen zwischen der Places-Kompatibilitätsbibliothek und der neuen eigenständigen Version des Places SDK for Android erläutert. Wenn Sie die Places-Kompatibilitätsbibliothek verwendet haben, anstatt zur neuen eigenständigen Version des Places SDK for Android zu migrieren, erfahren Sie in diesem Leitfaden, wie Sie Ihre Projekte so aktualisieren, dass die neue Version des Places SDK for Android verwendet wird.

Nach Version 2.6.0 des Places SDK for Android kann nur noch direkt über das SDK auf Funktionen und Fehlerkorrekturen zugegriffen werden. Google empfiehlt, so schnell wie möglich von der Kompatibilitätsbibliothek auf die neue Version des Places SDK for Android umzustellen.

Was hat sich geändert?

Die wichtigsten Änderungen sind:

  • Die neue Version des Places SDK for Android wird als statische Clientbibliothek bereitgestellt. Vor Januar 2019 war das Places SDK for Android über die Google Play-Dienste verfügbar. Seitdem wurde eine Places-Kompatibilitätsbibliothek bereitgestellt, um den Übergang zum neuen Places SDK for Android zu erleichtern.
  • Es gibt völlig neue Methoden.
  • Feldmasken werden jetzt für Methoden unterstützt, die Ortsdetails zurückgeben. Mithilfe von Feldmasken können Sie angeben, welche Arten von Ortsdaten zurückgegeben werden sollen.
  • Die Statuscodes, mit denen Fehler gemeldet werden, wurden verbessert.
  • Die automatische Vervollständigung unterstützt jetzt Sitzungstokens.
  • Die Ortsauswahl ist nicht mehr verfügbar.

Places-Kompatibilitätsbibliothek

Im Januar 2019 hat Google mit der Veröffentlichung der Version 1.0 des eigenständigen Places SDK for Android eine Kompatibilitätsbibliothek zur Unterstützung der Migration von der eingestellten Google Play-Dienste-Version des Places SDK for Android (com.google.android.gms:play-services-places) bereitgestellt.

Diese Kompatibilitätsbibliothek wurde vorübergehend bereitgestellt, um API-Aufrufe, die an die Google Play-Dienste-Version gerichtet sind, an die neue eigenständige Version weiterzuleiten und zu übersetzen, bis Entwickler ihren Code so migrieren konnten, dass die neuen Namen im eigenständigen SDK verwendet wurden. Für jede Version des Places SDK for Android, die von Version 1.0 bis Version 2.6.0 veröffentlicht wurde, wurde eine entsprechende Version der Places-Kompatibilitätsbibliothek veröffentlicht, um dieselben Funktionen bereitzustellen.

Einstellung der Entwicklung der Places-Kompatibilitätsbibliothek

Am 31. März 2022 wurden alle Versionen der Kompatibilitätsbibliothek für das Places SDK for Android eingestellt. Version 2.6.0 ist die letzte Version der Places-Kompatibilitätsbibliothek. Nach Version 2.6.0 des Places SDK for Android kann nur noch direkt über das SDK auf Funktionen und Fehlerkorrekturen zugegriffen werden.

Google empfiehlt die Migration zum Places SDK for Android, um auf neue Funktionen und wichtige Fehlerkorrekturen für Releases ab Version 2.6.0 zugreifen zu können. Wenn Sie derzeit die Kompatibilitätsbibliothek verwenden, folgen Sie der Anleitung unten im Abschnitt Places SDK for Android installieren, um zum Places SDK for Android zu migrieren.

Clientbibliothek installieren

Die neue Version des Places SDK for Android wird als statische Clientbibliothek bereitgestellt.

Verwenden Sie Maven, um Ihrem Android Studio-Projekt das Places SDK for Android hinzuzufügen:

  1. Wenn Sie derzeit die Places-Kompatibilitätsbibliothek verwenden:

    1. Ersetzen Sie im Abschnitt dependencies die folgende Zeile:

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

      Mit dieser Zeile können Sie zum Places SDK for Android wechseln:

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

  2. Wenn Sie derzeit die Play-Dienste-Version des Places SDK for Android verwenden:

    1. Ersetzen Sie im Abschnitt dependencies die folgende Zeile:

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

      Mit dieser Zeile können Sie zum Places SDK for Android wechseln:

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

  3. Synchronisiere dein Gradle-Projekt.

  4. Legen Sie minSdkVersion für Ihr Anwendungsprojekt auf 16 oder höher fest.

  5. Aktualisieren Sie Ihre „Powered by Google“-Assets:

    @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. Erstellen Sie Ihre App. Wenn aufgrund der Umstellung auf das Places SDK for Android Build-Fehler auftreten, finden Sie in den folgenden Abschnitten Informationen zur Behebung dieser Fehler.

Neuen Places SDK-Client initialisieren

Initialisieren Sie den neuen Places SDK-Client wie im folgenden Beispiel gezeigt:

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

Statuscodes

Der Statuscode für Fehler beim Grenzwert für die Anzahl der Abfragen pro Sekunde hat sich geändert. Fehler beim Limit für die Anzahl der Abfragen pro Sekunde werden jetzt über PlaceStatusCodes.OVER_QUERY_LIMIT zurückgegeben. Es gibt keine Limits für die Anzahl der Abfragen pro Tag mehr.

Die folgenden Statuscodes wurden hinzugefügt:

  • REQUEST_DENIED: Die Anfrage wurde abgelehnt. Mögliche Gründe sind z. B. folgende:

    • Es wurde kein API-Schlüssel angegeben.
    • Es wurde ein ungültiger API-Schlüssel angegeben.
    • Die Places API wurde in der Cloud Console nicht aktiviert.
    • Für einen API-Schlüssel wurden falsche Schlüsseleinschränkungen angegeben.
  • INVALID_REQUEST: Die Anfrage ist aufgrund eines fehlenden oder ungültigen Arguments ungültig.

  • NOT_FOUND: Für die Anfrage wurde kein Ergebnis gefunden.

Neue Methoden

Die neue Version des Places SDK for Android bietet brandneue Methoden, die für Konsistenz sorgen. Für alle neuen Methoden gilt Folgendes:

  • Für Endpunkte wird das Verb get nicht mehr verwendet.
  • Anfrage- und Antwortobjekte haben denselben Namen wie die entsprechende Clientmethode.
  • Anfragenobjekte haben jetzt Builder; erforderliche Parameter werden als Builder-Parameter übergeben.
  • Puffer werden nicht mehr verwendet.

In diesem Abschnitt werden die neuen Methoden vorgestellt und ihre Funktionsweise erläutert.

Ort anhand der ID abrufen

Mit fetchPlace() lassen sich Details zu einem bestimmten Ort abrufen. fetchPlace() funktioniert ähnlich wie getPlaceById().

So rufen Sie einen Ort ab:

  1. Rufen Sie fetchPlace() auf und übergeben Sie ein FetchPlaceRequest-Objekt mit einer Orts-ID und einer Liste von Feldern, in denen die zurückzugebenden Ortsdaten angegeben sind.

    // 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();
    
    
  2. Rufe addOnSuccessListener() auf, um den FetchPlaceResponse zu verarbeiten. Es wird ein einzelnes Place-Ergebnis zurückgegeben.

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

Fotos von Orten abrufen

Mit fetchPhoto() können Sie ein Foto eines Orts abrufen. fetchPhoto() gibt Fotos für einen Ort zurück. Das Muster für die Anforderung eines Fotos wurde vereinfacht. Sie können PhotoMetadata jetzt direkt über das Place-Objekt anfordern. Eine separate Anfrage ist nicht mehr erforderlich. Fotos dürfen eine maximale Breite oder Höhe von 1.600 Pixeln haben. fetchPhoto() funktioniert ähnlich wie getPhoto().

So rufen Sie Fotos von Orten ab:

  1. Richten Sie einen Anruf an fetchPlace() ein. Geben Sie in Ihrer Anfrage das Feld PHOTO_METADATAS an:

    List<Place.Field> fields = Arrays.asList(Place.Field.PHOTO_METADATAS);
    
  2. Rufen Sie ein Ortsobjekt ab. In diesem Beispiel wird fetchPlace() verwendet, Sie können aber auch findCurrentPlace() verwenden:

    FetchPlaceRequest placeRequest = FetchPlaceRequest.builder(placeId, fields).build();
    
  3. Fügen Sie ein OnSuccessListener hinzu, um die Fotometadaten aus dem resultierenden Place in der FetchPlaceResponse abzurufen. Verwenden Sie dann die resultierenden Fotometadaten, um eine Bitmap und einen Attributionstext abzurufen:

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

Orte anhand des Standorts des Nutzers finden

Mit findCurrentPlace() können Sie den aktuellen Standort des Geräts des Nutzers ermitteln. findCurrentPlace() gibt eine Liste von PlaceLikelihoods zurück, die Orte angeben, an denen sich das Gerät des Nutzers am wahrscheinlichsten befindet. findCurrentPlace() funktioniert ähnlich wie getCurrentPlace().

So rufen Sie den aktuellen Standort des Geräts des Nutzers ab:

  1. Ihre App muss die Berechtigungen ACCESS_FINE_LOCATION und ACCESS_WIFI_STATE anfordern. Der Nutzer muss die Berechtigung zum Zugriff auf seinen aktuellen Gerätestandort erteilen. Weitere Informationen finden Sie unter App-Berechtigungen anfordern.

  2. Erstellen Sie eine FindCurrentPlaceRequest mit einer Liste der zurückzugebenden Ortsdatentypen.

      // 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();
    
  3. Rufen Sie „findCurrentPlace“ auf und verarbeiten Sie die Antwort. Prüfen Sie zuerst, ob der Nutzer die Berechtigung zur Verwendung seines Gerätestandorts erteilt hat.

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

Automatische Vervollständigungen finden

Verwenden Sie findAutocompletePredictions(), um Ortsvorschläge als Reaktion auf Suchanfragen von Nutzern zurückzugeben. findAutocompletePredictions() funktioniert ähnlich wie getAutocompletePredictions().

Hier sehen Sie, wie findAutocompletePredictions() aufgerufen wird:

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

Sitzungstokens

Sitzungstokens fassen die Abfrage- und Auswahlphasen einer Nutzersuche zu Abrechnungszwecken zu einer separaten Sitzung zusammen. Wir empfehlen, Sitzungstokens für alle Sitzungen zu verwenden, bei denen eine automatische Vervollständigung erfolgt. Die Sitzung beginnt, wenn der Nutzer mit der Eingabe beginnt, und endet, wenn er einen Ort auswählt. Jede Sitzung kann mehrere Abfragen und eine Ortsauswahl umfassen. Sobald eine Sitzung beendet wird, ist das Token nicht mehr gültig. Ihre App muss für jede Sitzung ein neues Token generieren.

Feldmasken

Bei Methoden, die Ortsdetails zurückgeben, müssen Sie bei jeder Anfrage angeben, welche Arten von Ortsdaten zurückgegeben werden sollen. So können Sie sicherstellen, dass Sie nur Daten anfordern und bezahlen, die Sie tatsächlich verwenden.

Wenn Sie angeben möchten, welche Datentypen zurückgegeben werden sollen, übergeben Sie in FetchPlaceRequest ein Array von Place.Fields, wie im folgenden Beispiel gezeigt:

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

Eine Liste der Felder, die Sie in einer Feldmaske verwenden können, finden Sie unter Felder für Ortsdaten (neu) .

Weitere Informationen zu Places-Daten-SKUs

Updates für die Ortsauswahl und Autocomplete

In diesem Abschnitt werden die Änderungen an den Places-Widgets (Place Picker und Autocomplete) erläutert.

Programmatische automatische Vervollständigung

Die folgenden Änderungen wurden an autocomplete vorgenommen:

  • PlaceAutocomplete wird in Autocomplete umbenannt.
    • PlaceAutocomplete.getPlace wird in Autocomplete.getPlaceFromIntent umbenannt.
    • PlaceAutocomplete.getStatus wird in Autocomplete.getStatusFromIntent umbenannt.
  • PlaceAutocomplete.RESULT_ERROR wurde in AutocompleteActivity.RESULT_ERROR umbenannt. Die Fehlerbehandlung für das Autocomplete-Fragment hat sich NICHT geändert.

Ortsauswahl

Die Ortsauswahl wurde am 29. Januar 2019 eingestellt. Sie wurde am 29. Juli 2019 deaktiviert und ist nicht mehr verfügbar. Andernfalls wird eine Fehlermeldung angezeigt. Die Ortsauswahl wird vom neuen SDK nicht unterstützt.

Autocomplete-Widgets

Die Autocomplete-Widgets wurden aktualisiert:

  • Das Präfix Place wurde aus allen Kursen entfernt.
  • Unterstützung für Sitzungstokens hinzugefügt. Das Widget verwaltet Tokens automatisch im Hintergrund.
  • Unterstützung für Feldmasken hinzugefügt, mit denen Sie auswählen können, welche Arten von Ortsdaten zurückgegeben werden sollen, nachdem der Nutzer eine Auswahl getroffen hat.

In den folgenden Abschnitten wird beschrieben, wie Sie Ihrem Projekt ein Autocomplete-Widget hinzufügen.

AutocompleteFragment einbetten

So fügen Sie ein Autocomplete-Fragment hinzu:

  1. Fügen Sie dem XML-Layout Ihrer Aktivität ein Fragment hinzu, wie im folgenden Beispiel gezeigt.

    <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. So fügen Sie der Aktivität das Widget für die automatische Vervollständigung hinzu:

    • Initialisiere Places und übergebe dabei den Anwendungskontext und deinen API-Schlüssel.
    • Initialisieren Sie AutocompleteSupportFragment.
    • Rufen Sie setPlaceFields() auf, um die Arten von „Place“-Daten anzugeben, die Sie abrufen möchten.
    • Fügen Sie PlaceSelectionListener hinzu, um etwas mit dem Ergebnis zu tun und eventuelle Fehler zu behandeln.

    Im folgenden Beispiel wird gezeigt, wie einer Aktivität ein Autocomplete-Widget hinzugefügt wird:

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

Intent verwenden, um die Aktivität „Autofill“ zu starten

  1. Places initialisieren, indem App-Kontext und API-Schlüssel übergeben werden
  2. Verwenden Sie Autocomplete.IntentBuilder, um eine Intent-Anfrage zu erstellen, und geben Sie den gewünschten PlaceAutocomplete-Modus (Vollbild oder Overlay) an. Der Intent muss startActivityForResult aufrufen und einen Anfragecode übergeben, der den Intent identifiziert.
  3. Überschreiben Sie den onActivityResult-Callback, um den ausgewählten Ort zu erhalten.

Im folgenden Beispiel wird gezeigt, wie Sie mit einem Intent die automatische Vervollständigung starten und dann das Ergebnis verarbeiten:

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

Die Ortsauswahl ist nicht mehr verfügbar

Die Ortsauswahl wurde am 29. Januar 2019 eingestellt. Sie wurde am 29. Juli 2019 deaktiviert und ist nicht mehr verfügbar. Andernfalls wird eine Fehlermeldung angezeigt. Die Ortsauswahl wird vom neuen SDK nicht unterstützt.