Migracja do nowego klienta pakietu SDK Miejsc

W tym przewodniku opisujemy zmiany między biblioteką zgodności miejsc a nową, samodzielną wersją pakietu SDK Miejsc na Androida. Jeśli zamiast migracji do nowej, samodzielnej wersji pakietu SDK Miejsc na Androida użyłeś biblioteki zgodności miejsc, z tego przewodnika dowiesz się, jak zaktualizować projekty tak, by korzystały z nowej wersji pakietu SDK Miejsc na Androida.

Jedynym sposobem na uzyskanie dostępu do funkcji i poprawek błędów w pakiecie SDK Miejsc na Androida w wersji nowszej niż 2.6.0 będzie użycie pakietu SDK Miejsc na Androida. Google zaleca jak najszybsze zaktualizowanie pakietu SDK z biblioteki zgodności do nowego pakietu SDK do wersji na Androida.

Co się zmieniło?

Oto główne obszary zmian:

  • Nowa wersja pakietu Places SDK dla Androida jest dystrybuowana jako statyczna biblioteka klienta. Przed styczniem 2019 r. pakiet SDK Miejsc na Androida został udostępniony w Usługach Google Play. Od tego czasu udostępniliśmy bibliotekę zgodności Miejsc w celu ułatwienia przejścia na nowy pakiet Miejsca dla systemu Android.
  • Dostępne są zupełnie nowe metody.
  • Maski pól są teraz obsługiwane w przypadku metod, które zwracają szczegóły miejsca. Za pomocą masek pól można określić typy danych miejsca, które mają zostać zwrócone.
  • Ulepszyliśmy kody stanu używane do zgłaszania błędów.
  • Autouzupełnianie obsługuje teraz tokeny sesji.
  • Selektor miejsc nie jest już dostępny.

Biblioteka zgodności miejsc

W styczniu 2019 r., w wersji 1.0 samodzielnego pakietu SDK Miejsc na Androida, dodaliśmy do Google bibliotekę kompatybilności, która ułatwia migrację z wycofanej wersji pakietu Miejsca Google na Androida (com.google.android.gms:play-services-places).

Biblioteka ta była tymczasowo udostępniana do przekierowywania i tłumaczenia wywołań interfejsu API kierowanych na wersję Usług Google Play na nową, samodzielną wersję, dopóki deweloperzy nie będą mogli przenieść kodu, aby używać nowych nazw w samodzielnym pakiecie SDK. Dla każdej wersji pakietu SDK Miejsc na Androida, która została wydana od wersji 1.0 do wersji 2.6.0, została udostępniona odpowiadająca jej wersja biblioteki zgodności miejsc.

Blokowanie i wycofywanie biblioteki zgodności Miejsc

31 marca 2022 r. wycofamy wszystkie wersje bibliotek zgodności z pakietem SDK dla Androida. Wersja 2.6.0 to ostatnia wersja biblioteki zgodności Miejsc. Jedynym sposobem na uzyskanie dostępu do funkcji i poprawek błędów w SDK Miejsc na Androida w wersji nowszej niż 2.6.0 jest użycie pakietu SDK Miejsc na Androida.

Google zaleca przejście na pakiet SDK Miejsc na Androida, aby uzyskać dostęp do nowych funkcji i krytycznych poprawek błędów w wersjach powyżej wersji 2.6.0. Jeśli używasz biblioteki zgodności, wykonaj czynności opisane poniżej w sekcji Instalowanie pakietu SDK Miejsc na Androida, aby przeprowadzić migrację do pakietu SDK Miejsc na Androida.

Instalowanie biblioteki klienta

Nowa wersja pakietu Places SDK dla Androida jest dystrybuowana jako statyczna biblioteka klienta.

Użyj pakietu Maven, aby dodać pakiet SDK Miejsc na Androida do projektu Android Studio:

  1. Jeśli korzystasz z biblioteki zgodności Miejsc:

    1. Zastąp ten wiersz w sekcji dependencies:

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

      Za pomocą tego wiersza możesz przejść do pakietu Places SDK dla Androida:

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

  2. Jeśli obecnie korzystasz z pakietu SDK Usług na Androida w ramach Usług Google Play:

    1. Zastąp ten wiersz w sekcji dependencies:

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

      Za pomocą tego wiersza możesz przejść do pakietu Places SDK dla Androida:

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

  3. zsynchronizować projekt Gradle,

  4. Ustaw minSdkVersion projektu aplikacji na 16 lub więcej.

  5. Zaktualizuj zasoby „Technologia 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. Skompiluj aplikację. Jeśli zauważysz błędy kompilacji wynikające z konwersji na pakiet SDK Miejsc na Androida, zapoznaj się z informacjami poniżej, aby dowiedzieć się, jak rozwiązać te problemy.

Inicjowanie nowego klienta pakietu SDK Miejsc

Zainicjuj nowego klienta SDK do wyświetlania reklam w ten sposób:

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

Kody stanu

Zmienił się kod stanu błędów QPS. Błędy limitu zapytań na sekundę są teraz zwracane za pomocą PlaceStatusCodes.OVER_QUERY_LIMIT. Nie ma więcej limitów QPD.

Dodaliśmy te kody stanu:

  • REQUEST_DENIED – prośba została odrzucona. Możliwe przyczyny:

    • Nie podano klucza interfejsu API.
    • Podano nieprawidłowy klucz interfejsu API.
    • Interfejs Places API nie został włączony w konsoli Google Cloud.
    • Klucz interfejsu API został dostarczony z nieprawidłowymi ograniczeniami.
  • INVALID_REQUEST – żądanie jest nieprawidłowe z powodu brakującego lub nieprawidłowego argumentu.

  • NOT_FOUND – nie znaleziono wyników dla danego żądania

Nowe metody

W nowej wersji pakietu Places SDK dla Androida wprowadzono nowe metody, które zostały zaprojektowane z myślą o spójności. Wszystkie nowe metody muszą być zgodne z tymi zasadami:

  • Punkty końcowe nie używają już czasownika get.
  • Obiekty żądania i odpowiedzi mają taką samą nazwę jak odpowiednia metoda klienta.
  • Obiekty żądań mają teraz kreatory; wymagane parametry są przekazywane jako parametry konstruktora żądań.
  • Bufory nie są już używane.

W tej sekcji opisujemy nowe metody i pokazujemy, jak one działają.

Pobierz miejsce według identyfikatora

Aby uzyskać szczegółowe informacje o konkretnym miejscu, użyj właściwości fetchPlace(). fetchPlace() działa podobnie jak getPlaceById().

Aby pobrać miejsce, wykonaj te czynności:

  1. Wywołaj fetchPlace(), przekazując obiekt FetchPlaceRequest z identyfikatorem miejsca i listą pól, które określają dane miejsca do zwrócenia.

    // 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. Wywołaj addOnSuccessListener(), aby obsłużyć FetchPlaceResponse. Zwracany jest jeden wynik 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());
        }
    });
    

Pobieranie zdjęcia miejsca

Użyj fetchPhoto(), aby uzyskać zdjęcie miejsca. fetchPhoto() zwraca zdjęcia danego miejsca. Wzorzec żądania zdjęcia został uproszczony. Teraz możesz przesłać żądanie PhotoMetadata bezpośrednio z obiektu Place; osobne żądanie nie jest już konieczne. Maksymalna szerokość lub wysokość obrazu to 1600 pikseli. fetchPhoto() działa podobnie jak getPhoto().

Aby pobrać zdjęcia miejsca, wykonaj te czynności:

  1. Skonfiguruj połączenie pod numer fetchPlace(). Pamiętaj, aby w żądaniu uwzględnić pole PHOTO_METADATAS:

    List<Place.Field> fields = Arrays.asList(Place.Field.PHOTO_METADATAS);
    
  2. Pobierz obiekt Place (w tym przykładzie korzystamy z fetchPlace(), ale możesz też użyć findCurrentPlace()):

    FetchPlaceRequest placeRequest = FetchPlaceRequest.builder(placeId, fields).build();
    
  3. Dodaj OnSuccessListener, aby pobrać metadane zdjęcia z Place w FetchPlaceResponse, a następnie użyj metadanych zdjęć, aby uzyskać bitmapę i tekst informacji o autorze:

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

Znajdź miejsce na podstawie lokalizacji użytkownika

Użyj findCurrentPlace(), aby znaleźć bieżącą lokalizację urządzenia użytkownika. findCurrentPlace() zwraca listę PlaceLikelihood elementów wskazujących, gdzie prawdopodobnie znajduje się urządzenie użytkownika. findCurrentPlace() działa podobnie jak getCurrentPlace().

Aby sprawdzić bieżącą lokalizację urządzenia użytkownika, wykonaj te czynności:

  1. Upewnij się, że aplikacja prosi o uprawnienia ACCESS_FINE_LOCATION i ACCESS_WIFI_STATE. Użytkownik musi zezwolić na dostęp do bieżącej lokalizacji urządzenia. Więcej informacji znajdziesz na stronie Prośby o dostęp do aplikacji.

  2. Utwórz FindCurrentPlaceRequest, w tym listę typów danych o miejscach do zwrócenia.

      // 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. Wywołaj metodę ZnajdźCurrentPlace i zajmij się jej odpowiedzią. Najpierw sprawdź, czy użytkownik wyraził zgodę na korzystanie z lokalizacji urządzenia.

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

Znajdowanie podpowiedzi autouzupełniania

Użyj findAutocompletePredictions(), aby zwrócić podpowiedzi dotyczące miejsc w odpowiedzi na zapytania użytkowników. findAutocompletePredictions() działa podobnie jak getAutocompletePredictions().

Oto przykład wywołania 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());
   }
});

Tokeny sesji

Tokeny sesji grupują fazy zapytania i wyboru użytkownika w oddzielną sesję na potrzeby płatności. Zalecamy używanie tokenów sesji dla wszystkich sesji autouzupełniania. Sesja rozpoczyna się, gdy użytkownik zacznie wpisywać zapytanie, i kończy się, gdy użytkownik wybierze miejsce. Każda sesja może mieć wiele zapytań, po których następuje jeden wybór miejsca. Po zakończeniu sesji token jest już nieważny. Aplikacja musi wygenerować nowy token dla każdej sesji.

Maski pól

W metodach, które zwracają szczegóły miejsca, musisz określić typy danych miejsca, które mają być zwracane w przypadku każdego żądania. Dzięki temu będziesz mieć pewność, że żądania danych, których rzeczywiście używasz, są wykorzystywane do opłacania (i opłacania tych kosztów).

Aby określić, które typy danych zostaną zwrócone, przekaż tablicę Place.Field w obiekcie FetchPlaceRequest, jak w tym przykładzie:

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

Możesz użyć jednego lub kilku z tych pól:

  • 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

Więcej informacji o kodach SKU danych dotyczących miejsc.

Aktualizacje selektora miejsc i autouzupełniania

W tej sekcji opisano zmiany w widżecie Miejsca (selektor miejsc i autouzupełnianie).

Autouzupełnianie

Wprowadziliśmy zmiany autouzupełniania:

  • Nazwa pliku PlaceAutocomplete została zmieniona na Autocomplete.
    • Nazwa pliku PlaceAutocomplete.getPlace została zmieniona na Autocomplete.getPlaceFromIntent.
    • Nazwa pliku PlaceAutocomplete.getStatus została zmieniona na Autocomplete.getStatusFromIntent.
  • Nazwa pliku PlaceAutocomplete.RESULT_ERROR została zmieniona na AutocompleteActivity.RESULT_ERROR (obsługa błędów we fragmencie autouzupełniania NIE została zmieniona).

Selektor miejsc

Selektor miejsc został wycofany 29 stycznia 2019 r. Została wyłączona 29 lipca 2019 roku i nie jest już dostępna. Dalsze używanie usługi spowoduje wyświetlenie komunikatu o błędzie. Nowy pakiet SDK nie obsługuje selektora miejsc.

Widżety autouzupełniania

Widżety autouzupełniania zostały zaktualizowane:

  • Prefiks Place został usunięty ze wszystkich zajęć.
  • Dodaliśmy obsługę tokenów sesji. Widżet automatycznie zarządza tokenami w tle.
  • Dodaliśmy obsługę masek pól, dzięki którym możesz wybrać typy danych o miejscach, które mają być zwracane po dokonaniu wyboru przez użytkownika.

W kolejnych sekcjach pokazujemy, jak dodać do projektu widżet autouzupełniania.

Umieść element AutocompleteFragment

Aby dodać fragment autouzupełniania, wykonaj te czynności:

  1. Dodaj fragment kodu do układu XML aktywności, tak jak w przykładzie poniżej.

    <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. Aby dodać do aktywności widżet autouzupełniania, wykonaj te czynności:

    • Inicjuj Places, przekazując kontekst aplikacji i klucz interfejsu API.
    • Zainicjuj instancję AutocompleteSupportFragment.
    • Wywołaj setPlaceFields(), aby wskazać rodzaje danych o miejscach, które chcesz uzyskiwać.
    • Dodaj PlaceSelectionListener, aby wykonać jakąś czynność związaną z wynikiem, a także naprawić błędy, które mogą wystąpić.

    Poniższy przykład pokazuje dodawanie widżetu autouzupełniania do aktywności:

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

Zamiar uruchomienia autouzupełniania

  1. Inicjowanie Places przez przekazanie kontekstu aplikacji i klucza interfejsu API
  2. Użyj metody Autocomplete.IntentBuilder, aby utworzyć intencję, przekazując wybrany tryb PlaceAutocomplete (pełny ekran lub nakładka). Intencja musi wywoływać metodę startActivityForResult, przekazując kod żądania, który identyfikuje intencję.
  3. Zastąp wywołanie zwrotne onActivityResult, aby otrzymać wybrane miejsce.

Poniższy przykład pokazuje, jak za pomocą zamiaru uruchomić autouzupełnianie, a następnie obsługiwać wynik:

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

Selektor miejsc nie jest już dostępny

Selektor miejsc został wycofany 29 stycznia 2019 r. Została wyłączona 29 lipca 2019 roku i nie jest już dostępna. Dalsze używanie usługi spowoduje wyświetlenie komunikatu o błędzie. Nowy pakiet SDK nie obsługuje selektora miejsc.