Migracja do nowego klienta pakietu SDK Miejsc

Deweloperzy z Europejskiego Obszaru Gospodarczego (EOG)

W tym przewodniku wyjaśniamy różnice między biblioteką zgodności Places a nową samodzielną wersją pakietu Places SDK na Androida. Jeśli zamiast przejść na nową samodzielną wersję pakietu Places SDK na Androida używasz biblioteki zgodności Places, ten przewodnik pokaże Ci, jak zaktualizować projekty, aby korzystać z nowej wersji pakietu Places SDK na Androida.

Jedynym sposobem na uzyskanie dostępu do funkcji i poprawek błędów w pakiecie SDK Miejsc na Androida w wersji powyżej 2.6.0 jest korzystanie z pakietu SDK Miejsc na Androida. Zalecamy jak najszybsze przejście z biblioteki zgodności na nową wersję pakietu Places SDK na Androida.

Błąd: 9005 PLACES_API_RATE_LIMIT_EXCEEDED

Co się zmieniło?

Główne obszary zmian to:

  • Nowa wersja pakietu SDK Miejsc na Androida jest rozpowszechniana jako statyczna biblioteka klienta. Przed styczniem 2019 r. pakiet SDK Miejsc na Androida był dostępny w Usługach Google Play. Od tego czasu udostępniliśmy bibliotekę zgodności Miejsc, aby ułatwić przejście na nowy pakiet Places SDK na Androida.
  • zupełnie nowe metody.
  • W przypadku metod zwracających szczegóły miejsca obsługiwane są teraz maski pól. Za pomocą masek pól możesz określić, jakie typy danych o miejscu mają być zwracane.
  • 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.

Informacje o bibliotece zgodności Miejsc

W styczniu 2019 r. wraz z wersją 1.0 samodzielnego pakietu SDK Miejsc na Androida Google udostępnił bibliotekę zgodności, która ułatwia migrację z wycofanej wersji pakietu SDK Miejsc na Androida w Usługach Google Play (com.google.android.gms:play-services-places).

Ta biblioteka zgodności została udostępniona tymczasowo, aby przekierowywać i tłumaczyć wywołania interfejsu API kierowane do wersji Usług Google Play na nową wersję samodzielną, 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 wydanej od wersji 1.0 do wersji 2.6.0 została udostępniona odpowiednia wersja biblioteki zgodności Miejsc, która zapewnia równoważną funkcjonalność.

Wstrzymanie i wycofanie biblioteki zgodności Miejsc

Wszystkie wersje biblioteki zgodności pakietu SDK Miejsc na Androida zostały wycofane 31 marca 2022 r. Wersja 2.6.0 to ostatnia wersja biblioteki zgodności Miejsc. Jedynym sposobem na dostęp do funkcji i poprawek błędów w pakiecie SDK Miejsc na Androida w wersji powyżej 2.6.0 jest korzystanie z pakietu SDK Miejsc na Androida.

Aby uzyskać dostęp do nowych funkcji i ważnych poprawek błędów w wersjach powyżej 2.6.0, zalecamy przejście na pakiet Places SDK na Androida. Jeśli obecnie korzystasz z biblioteki zgodności, wykonaj czynności opisane w sekcji Instalowanie pakietu SDK Miejsc na Androida, aby przejść na pakiet SDK Miejsc na Androida.

Instalowanie biblioteki klienta

Nowa wersja pakietu SDK Miejsc na Androida jest rozpowszechniana jako statyczna biblioteka klienta.

Aby dodać pakiet Places SDK na Androida do projektu Android Studio, użyj Maven:

  1. Jeśli obecnie 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'

      Aby przejść na pakiet SDK Miejsc na Androida, użyj tego wiersza:

          implementation("com.google.android.libraries.places:places:4.3.1")

  2. Jeśli obecnie używasz wersji pakietu SDK Miejsc na Androida w Usługach Play:

    1. Zastąp ten wiersz w sekcji dependencies:

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

      Aby przejść na pakiet SDK Miejsc na Androida, użyj tego wiersza:

          implementation("com.google.android.libraries.places:places:4.3.1")

  3. Zsynchronizuj projekt Gradle.

  4. Ustaw wartość minSdkVersion w projekcie aplikacji na 23 lub wyższą.

  5. Zaktualizuj komponenty „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. Skompiluj aplikację. Jeśli podczas kompilacji wystąpią błędy spowodowane przejściem na pakiet Places SDK na Androida, zapoznaj się z sekcjami poniżej, aby dowiedzieć się, jak je rozwiązać.

Inicjowanie nowego klienta pakietu Places SDK

Zainicjuj nowego klienta pakietu SDK Miejsc, jak pokazano w tym przykładzie:

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

Zmieniliśmy kod stanu błędów związanych z limitem zapytań na sekundę. Błędy limitu zapytań są teraz zwracane za pomocą PlaceStatusCodes.OVER_QUERY_LIMIT. Nie ma już limitów QPD.

Dodano 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 Cloud.
    • Podano klucz interfejsu API 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

Nowa wersja pakietu SDK Miejsc na Androida zawiera zupełnie nowe metody, które zostały zaprojektowane z myślą o spójności. Wszystkie nowe metody są zgodne z tymi zasadami:

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

W tej sekcji przedstawiamy nowe metody i wyjaśniamy, jak działają.

Pobieranie miejsca według identyfikatora

Użyj fetchPlace(), aby uzyskać szczegółowe informacje o konkretnym miejscu. fetchPlace() działa podobnie do getPlaceById().

Aby pobrać miejsce, wykonaj te czynności:

  1. Wywołaj metodę fetchPlace(), przekazując obiekt FetchPlaceRequest, który określa identyfikator miejsca i listę pól określających 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.DISPLAY_NAME);
    
    // Construct a request object, passing the place ID and fields array.
    FetchPlaceRequest request = FetchPlaceRequest.builder(placeId, placeFields)
            .build();
    
    
  2. Zadzwoń pod numer addOnSuccessListener(), aby rozwiązać problem FetchPlaceResponse. Zwracany jest pojedynczy 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 pobrać zdjęcie miejsca. fetchPhoto() zwraca zdjęcia miejsca. Uprościliśmy wzorzec prośby o zdjęcie. Możesz teraz wysyłać żądania PhotoMetadata bezpośrednio z obiektu Place. Nie jest już potrzebne osobne żądanie. Zdjęcia mogą mieć maksymalną szerokość lub wysokość 1600 pikseli. fetchPhoto() działa podobnie do getPhoto().

Aby pobrać zdjęcia miejsca:

  1. Ustaw połączenie z numerem fetchPlace(). Pamiętaj, aby w prośbie uwzględnić pole PHOTO_METADATAS:

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

    FetchPlaceRequest placeRequest = FetchPlaceRequest.builder(placeId, fields).build();
    
  3. Dodaj OnSuccessListener, aby pobrać metadane zdjęcia z wynikowego elementu PlaceFetchPlaceResponse, a następnie użyj tych metadanych, aby pobrać bitmapę i tekst z informacjami 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());
            }
        });
    });
    

Znajdowanie miejsca na podstawie lokalizacji użytkownika

Użyj findCurrentPlace(), aby znaleźć bieżącą lokalizację urządzenia użytkownika. findCurrentPlace() zwraca listę PlaceLikelihoods wskazujących miejsca, w których urządzenie użytkownika najprawdopodobniej się znajduje. findCurrentPlace() działa podobnie do getCurrentPlace().

Aby uzyskać aktualną lokalizację urządzenia użytkownika, wykonaj te czynności:

  1. Upewnij się, że aplikacja prosi o uprawnienia ACCESS_FINE_LOCATIONACCESS_WIFI_STATE. Użytkownik musi zezwolić na dostęp do lokalizacji bieżącego urządzenia. Szczegółowe informacje znajdziesz w sekcji Request App Permissions (Prośba o uprawnienia 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.DISPLAY_NAME);
    
      // Use the builder to create a FindCurrentPlaceRequest.
      FindCurrentPlaceRequest request =
              FindCurrentPlaceRequest.builder(placeFields).build();
    
  3. Wywołaj funkcję findCurrentPlace i obsłuż odpowiedź, sprawdzając najpierw, czy użytkownik przyznał uprawnienia do korzystania 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 zwracać prognozy miejsc w odpowiedzi na zapytania użytkownika. findAutocompletePredictions() działa podobnie do getAutocompletePredictions().

Poniższy przykład pokazuje wywołanie funkcji 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 wyszukiwania użytkownika w osobną sesję na potrzeby rozliczeń. W przypadku wszystkich sesji autouzupełniania zalecamy używanie tokenów sesji. Sesja rozpoczyna się, gdy użytkownik zaczyna wpisywać zapytanie, a kończy, gdy wybierze miejsce. Każda sesja może zawierać wiele zapytań, po których następuje wybór jednego miejsca. Po zakończeniu sesji token traci ważność. Aplikacja musi generować nowy token dla każdej sesji.

Maski pól

W metodach, które zwracają szczegóły miejsca, musisz określić, jakie typy danych o miejscu mają być zwracane w odpowiedzi na każde żądanie. Dzięki temu masz pewność, że prosisz tylko o dane, których będziesz używać, i za nie płacisz.

Aby określić, które typy danych mają być zwracane, przekaż tablicę Place.FieldFetchPlaceRequest, jak pokazano w tym przykładzie:

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

Listę pól, których możesz używać w masce pól, znajdziesz w artykule Pola danych o miejscach (nowe) .

Dowiedz się więcej o kodach SKU danych o miejscach.

Aktualizacje selektora miejsc i autouzupełniania

W tej sekcji opisujemy zmiany w widżetach Miejsc (selektorze miejsca i autouzupełnianiu).

Automatyzacja autouzupełniania

autouzupełnianiu wprowadzono te zmiany:

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

Selektor miejsca

Selektor miejsc został wycofany 29 stycznia 2019 roku. Została wyłączona 29 lipca 2019 roku i nie jest już dostępna. Dalsze korzystanie z tej funkcji 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.
  • Dodano obsługę masek pól, które umożliwiają wybór typów danych o miejscu, jakie mają być zwracane po dokonaniu wyboru przez użytkownika.

Z sekcji poniżej dowiesz się, jak dodać do projektu widżet autouzupełniania.

Umieszczanie AutocompleteFragment

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

  1. Dodaj fragment do układu XML aktywności, jak pokazano w tym przykładzie.

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

    • Zainicjuj Places, przekazując kontekst aplikacji i klucz interfejsu API.
    • Zainicjuj obiekt AutocompleteSupportFragment.
    • Wywołaj setPlaceFields(), aby wskazać typy danych o miejscach, które chcesz uzyskać.
    • Dodaj PlaceSelectionListener, aby wykonać działanie na wyniku, a także obsłużyć wszelkie błędy, które mogą wystąpić.

    Poniższy przykład pokazuje, jak dodać widżet 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.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);
        }
    });
    

Używanie intencji do uruchamiania działania autouzupełniania

  1. Zainicjuj Places, przekazując kontekst aplikacji i klucz interfejsu API.
  2. Użyj Autocomplete.IntentBuilder, aby utworzyć intencję, przekazując żądany PlaceAutocomplete tryb (pełnoekranowy lub nakładka). Intencja musi wywoływać metodę startActivityForResult, przekazując kod żądania, który identyfikuje Twoją intencję.
  3. Zastąp wywołanie zwrotne onActivityResult, aby otrzymać wybrane miejsce.

Ten przykład pokazuje, jak użyć intencji do uruchomienia autouzupełniania, a następnie przetworzyć 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.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.
            }
        }
    }

Selektor miejsc nie jest już dostępny

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