Migracja do nowego klienta pakietu SDK Miejsc

W tym przewodniku wyjaśniamy różnice między biblioteką zgodności Places a nową samodzielną wersją pakietu SDK Places na Androida. Jeśli zamiast migracji do nowej samodzielnej wersji pakietu Places SDK na Androida używasz biblioteki kompatybilności z miejscami, w tym przewodniku znajdziesz informacje o tym, jak zaktualizować swoje projekty, aby używały nowej wersji pakietu Places SDK na Androida.

Jedynym sposobem na dostęp do funkcji i poprawek błędów w pakiecie Places SDK na Androida w wersji 2.6.0 lub nowszej jest użycie pakietu Places SDK na Androida. Google zaleca jak najszybsze przejście z biblioteki zgodności na nową wersję pakietu SDK Map Google na Androida.

Co się zmieniło?

Główne obszary zmian to:

  • Nowa wersja pakietu SDK Places na Androida jest rozpowszechniana jako statyczna biblioteka klienta. Przed styczniem 2019 r. pakiet SDK do aplikacji Miejsca na Androida był dostępny w Usługach Google Play. Od tego czasu udostępniliśmy bibliotekę zgodności z Places, aby ułatwić przejście na nowy pakiet SDK Places na Androida.
  • Dostępne są całkowicie nowe metody.
  • Maski pól są teraz obsługiwane w przypadku metod zwracających szczegóły miejsca. Za pomocą masek pól możesz określić, jakie typy danych o miejscach mają zostać zwrócone.
  • Ulepszono kody stanu używane do zgłaszania błędów.
  • Autouzupełnianie obsługuje teraz tokeny sesji.
  • Wybór miejsca nie jest już dostępny.

Biblioteka zgodności w usłudze Places

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

Ta biblioteka zgodności została tymczasowo udostępniona, aby przekierowywać i tłumaczyć wywołania interfejsu API kierowane do wersji Usług Google Play na nową wersję samodzielną, do czasu, gdy deweloperzy będą mogli przenieść swój kod na nowe nazwy w pakiecie SDK samodzielnym. W przypadku każdej wersji pakietu Places SDK na Androida (od wersji 1.0 do 2.6.0) została wydana odpowiednia wersja biblioteki zgodności z Places, która zapewnia równoważną funkcjonalność.

Zamrożenie i wycofanie biblioteki zgodności z Places

Od 31 marca 2022 r. wszystkie wersje biblioteki zgodności pakietu SDK Places na Androida są wycofane. Wersja 2.6.0 jest ostatnią wersją biblioteki kompatybilności Places. Jedynym sposobem na dostęp do funkcji i poprawek błędów w pakiecie Places SDK for Android w wersji 2.6.0 lub nowszej jest użycie pakietu Places SDK for Android.

Google zaleca przejście na pakiet Places SDK na Androida, aby uzyskać dostęp do nowych funkcji i krytycznych poprawek błędów w wersjach wyższych niż 2.6.0. Jeśli obecnie używasz biblioteki zgodności, wykonaj czynności opisane w sekcji Instalowanie pakietu Places SDK na Androida, aby przejść na Places SDK na Androida.

Instalowanie biblioteki klienta

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

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

  1. Jeśli obecnie używasz biblioteki kompatybilności z Google Places:

    1. W sekcji dependencies zastąp ten wiersz:

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

      Aby przełączyć się na pakiet SDK Miejsc na Androida:

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

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

    1. W sekcji dependencies zastąp ten wiersz:

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

      Aby przełączyć się na pakiet SDK Miejsc na Androida:

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

  3. Zsynchronizuj projekt Gradle.

  4. Ustaw wartość minSdkVersion dla projektu aplikacji na 16 lub wyższą.

  5. Zaktualizuj komponenty „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. Utwórz aplikację. Jeśli podczas jej tworzenia pojawią się błędy spowodowane konwersją na pakiet SDK Places na Androida, zapoznaj się z sekcjami poniżej, aby dowiedzieć się, jak je rozwiązać.

Inicjowanie nowego klienta pakietu SDK Places

Wczytaj nowego klienta pakietu SDK Places 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 związanych z limitem QPS. Błędy związane z ograniczeniem liczby zapytań na sekundę są teraz zwracane w usłudze 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 API z nieprawidłowymi ograniczeniami.
  • INVALID_REQUEST – żądanie jest nieprawidłowe z powodu braku lub nieprawidłowego argumentu.

  • NOT_FOUND – nie znaleziono żadnych wyników dla danego zapytania.

Nowe metody

Nowa wersja pakietu SDK Places na Androida wprowadza zupełnie nowe metody, które zostały zaprojektowane w celu zapewnienia spójności. Wszystkie nowe metody:

  • Punkty końcowe nie używają już czasownika get.
  • Obiekty żądania i odpowiedzi mają tę samą nazwę co odpowiadające im metody 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 sposób ich działania.

Pobieranie miejsca według identyfikatora

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

Aby pobrać dane o miejscu:

  1. Wywołaj funkcję fetchPlace(), przekazując obiekt FetchPlaceRequest określający identyfikator Miejsca oraz listę polów określających dane Miejsca, które mają zostać zwrócone.

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

Aby pobrać zdjęcie miejsca, kliknij fetchPhoto(). fetchPhoto() zwraca zdjęcia danego miejsca. Uproszczony został schemat przesyłania prośby o zdjęcie. Teraz możesz poprosić o PhotoMetadata bezpośrednio z obiektu Place. Nie musisz już wysyłać osobnej prośby. Zdjęcia mogą mieć maksymalną szerokość lub wysokość 1600 pikseli. fetchPhoto() działa podobnie do funkcji getPhoto().

Aby pobrać zdjęcia miejsca:

  1. Skonfiguruj połączenie z fetchPlace(). Pamiętaj, aby w prośbie podać pole PHOTO_METADATAS:

    List<Place.Field> fields = Arrays.asList(Place.Field.PHOTO_METADATAS);
    
  2. Pobierz obiekt Miejsce (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 uzyskać metadane zdjęcia z wynikającego PlaceFetchPlaceResponse, a następnie użyj uzyskanych metadanych, aby uzyskać bitmapę i tekst atrybucji:

    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źć aktualną lokalizację urządzenia użytkownika. findCurrentPlace()zwraca listę PlaceLikelihood, która wskazuje miejsca, w których urządzenie użytkownika znajduje się najprawdopodobniej. Funkcja findCurrentPlace() działa podobnie do funkcji getCurrentPlace().

Aby uzyskać aktualną lokalizację urządzenia użytkownika:

  1. Upewnij się, że aplikacja prosi o uprawnienia ACCESS_FINE_LOCATIONACCESS_WIFI_STATE. Użytkownik musi przyznać uprawnienia do dostępu do bieżącej lokalizacji urządzenia. Więcej informacji znajdziesz w artykule Wysyłanie prośby o przyznanie uprawnień aplikacji.

  2. Utwórz FindCurrentPlaceRequest, uwzględniając 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 findCurrentPlace i obsługuj odpowiedź, najpierw sprawdzając, czy użytkownik zezwolił 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 parametru findAutocompletePredictions(), aby zwracać prognozy dotyczące miejsc w odpowiedzi na zapytania użytkowników. Funkcja findAutocompletePredictions() działa podobnie do funkcji 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

Na potrzeby rozliczeń tokeny sesji łączą fazy zapytania i wyboru w jedną sesję. Zalecamy używanie tokenów sesji we wszystkich sesjach autouzupełniania. Sesja rozpoczyna się, gdy użytkownik zacznie 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 wygenerować nowy token na każdą sesję.

Maski pól

W metodach, które zwracają szczegóły miejsca, musisz określić, jakie typy danych o miejscach mają być zwracane w każdej prośbie. Dzięki temu masz pewność, że żądasz (i płacisz) tylko za dane, których faktycznie używasz.

Aby określić, które typy danych mają zostać zwrócone, prześlij tablicę wartości Place.Field w parametry funkcji FetchPlaceRequest, jak 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 pola, znajdziesz w sekcji Pola danych o miejscach (nowe) .

Dowiedz się więcej o kodzie SKU usługi Places Data.

Aktualizacje selektora miejsc i autouzupełniania

W tej sekcji opisujemy zmiany w widżetach Miejsca (wybieranie miejsc i autouzupełnianie).

Automatyczne wypełnianie formularzy

autocomplete wprowadzono następujące 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.
  • Nazwa PlaceAutocomplete.RESULT_ERROR została zmieniona na AutocompleteActivity.RESULT_ERROR (obsługa błędów w przypadku fragmentu autouzupełniania się nie zmieniła).

Selektor miejsca

Selektor miejsc został wycofany 29 stycznia 2019 r. Został on wyłączony 29 lipca 2019 r. i nie jest już dostępny. Dalsze korzystanie z tego konta spowoduje wyświetlenie komunikatu o błędzie. Nowe SDK nie obsługuje selektora miejsc.

Widżety autouzupełniania

Widgety autouzupełniania zostały zaktualizowane:

  • W przypadku wszystkich klas usunięto prefiks Place.
  • Dodano obsługę tokenów sesji. Widget automatycznie zarządza tokenami w tle.
  • Dodano obsługę masek pól, które umożliwiają wybranie, jakie typy danych o miejscach mają być zwracane po dokonaniu przez użytkownika wyboru.

W następnych sekcjach dowiesz się, jak dodać do projektu widżet autouzupełniania.

Wstawianie AutocompleteFragment

Aby dodać fragment autouzupełniania:

  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:

    • Inicjalizacja Places z przekazaniem kontekstu aplikacji i klucza interfejsu API.
    • Inicjalizacja AutocompleteSupportFragment.
    • Zadzwoń pod numer setPlaceFields(), aby wskazać typy danych o miejscach, które chcesz uzyskać.
    • Dodaj instrukcję PlaceSelectionListener, aby wykonać coś z wynikiem, a także obsłużyć ewentualne błędy.

    Ten 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.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życie intencji do uruchomienia aktywności autouzupełniania

  1. Inicjalizacja Places z przekazaniem kontekstu aplikacji i klucza API
  2. Użyj elementu Autocomplete.IntentBuilder, aby utworzyć intencję, przekazując żądany tryb PlaceAutocomplete (pełnoekranowy lub nakładka). Musi on wywoływać funkcję startActivityForResult, przekazując kod żądania, który identyfikuje intencję.
  3. Zastąpić wywołanie zwrotne onActivityResult, aby otrzymać wybrane miejsce.

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

Wybieranie miejsc jest niedostępne

Selektor miejsc został wycofany 29 stycznia 2019 r. Został on wyłączony 29 lipca 2019 r. i nie jest już dostępny. Dalsze korzystanie z tego konta spowoduje wyświetlenie komunikatu o błędzie. Nowe SDK nie obsługuje selektora miejsc.