W tym przewodniku opisujemy zmiany między biblioteką zgodności Miejsc a nową, samodzielną wersją pakietu SDK Miejsc Google na Androida. Jeśli korzystasz z biblioteki zgodności Miejsc, a nie przechodzisz na nową, samodzielną wersję pakietu Miejsc SDK na Androida, z tego przewodnika dowiesz się, jak zaktualizować projekty, aby korzystały z nowej wersji pakietu Miejsca SDK na Androida.
Jedynym sposobem uzyskania dostępu do funkcji i poprawek błędów w pakiecie Miejsc SDK na Androida w wersji nowszej niż 2.6.0 jest skorzystanie z pakietu Miejsca SDK na Androida. Google zaleca jak najszybsze przejście z biblioteki zgodności na nową wersję pakietu Places SDK na Androida.
Co się zmieniło?
Główne obszary zmian to:
- Nowa wersja pakietu Miejsca SDK na Androida jest rozpowszechniana jako statyczna biblioteka klienta. Przed styczniem 2019 r. pakiet Miejsca SDK na Androida był dostępny w Usługach Google Play. Od tego czasu udostępniliśmy bibliotekę zgodności Miejsc, która ma ułatwić przejście na nowy pakiet SDK Miejsc Google na Androida.
- Dostępne są zupełnie nowe metody.
- Maski pól są teraz obsługiwane w przypadku metod, które zwracają szczegóły miejsc. Możesz użyć masek pól, by określić typy danych miejsc, które 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.
Biblioteka zgodności Miejsc – informacje
W styczniu 2019 r. udostępniliśmy wersję 1.0 autonomicznego pakietu SDK Miejsc na Androida, aby ułatwić sobie migrację z wycofanej wersji pakietu Miejsca SDK na Androida przeznaczonego do Usług Google Play (com.google.android.gms:play-services-places
).
Ta biblioteka zgodności została tymczasowo udostępniona do przekierowywania i tłumaczenia wywołań interfejsu API kierowanych na nową, samodzielną wersję Usług Google Play do czasu, aż deweloperzy będą mogli przenieść swój kod, 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 od 1.0 do 2.6.0, opublikowano odpowiednią wersję biblioteki zgodności Miejsc Google, aby zapewnić jej równoważne funkcje.
Blokowanie i wycofywanie biblioteki zgodności Miejsc
Wszystkie wersje biblioteki zgodności pakietu Miejsca SDK na Androida zostały wycofane 31 marca 2022 r. 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 pakiecie Miejsc SDK na Androida w wersji nowszej niż 2.6.0 jest skorzystanie z pakietu Miejsca SDK na Androida.
Google zaleca przejście na pakiet Miejsca SDK na Androida w celu uzyskania dostępu do nowych funkcji i krytycznych poprawek w wersjach nowszych niż 2.6.0. Jeśli obecnie używasz biblioteki zgodności, wykonaj czynności opisane poniżej w sekcji Instalowanie pakietu Miejsca SDK na Androida, by przejść na pakiet Miejsca SDK na Androida.
Instalowanie biblioteki klienta
Nowa wersja pakietu Miejsca SDK na Androida jest rozpowszechniana jako statyczna biblioteka klienta.
Użyj narzędzia Maven, aby dodać do projektu Android Studio pakiet SDK Miejsc Google na Androida:
Jeśli korzystasz obecnie z biblioteki zgodności Miejsc:
Zastąp następujący wiersz w sekcji
dependencies
:implementation 'com.google.android.libraries.places:places-compat:X.Y.Z'
Po tym wierszu przejdź do pakietu Miejsca SDK na Androida:
implementation 'com.google.android.libraries.places:places:3.1.0'
Jeśli używasz obecnie pakietu SDK Miejsc Google w wersji Usług Google Play na Androida:
Zastąp następujący wiersz w sekcji
dependencies
:implementation 'com.google.android.gms:play-services-places:X.Y.Z'
Po tym wierszu przejdź do pakietu Miejsca SDK na Androida:
implementation 'com.google.android.libraries.places:places:3.1.0'
Zsynchronizuj projekt Gradle.
Ustaw dla projektu aplikacji
minSdkVersion
wartość 16 lub wyższą.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
Utwórz aplikację. Jeśli w wyniku konwersji na pakiet Miejsca SDK na Androida zauważysz błędy kompilacji, przeczytaj poniższe informacje, by dowiedzieć się, jak rozwiązywać te problemy.
Zainicjuj nowego klienta pakietu Miejsca SDK
Zainicjuj nowego klienta pakietu Miejsca SDK w sposób podany 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
Kod stanu błędów limitu zapytań na sekundę uległ zmianie. Błędy limitu zapytań na sekundę są teraz zwracane przez 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 Miejsca API nie został włączony w konsoli Google 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 Miejsca SDK na Androida wprowadza zupełnie nowe metody, które zostały zaprojektowane z myślą o spójności. Wszystkie nowe metody są zgodne z tymi zasadami:
- W punktach końcowych nie ma już czasownika
get
. - Obiekty żądań i odpowiedzi mają taką samą nazwę jak odpowiadające im metody klienta.
- Obiekty żądań mają teraz monterów. Wymagane parametry są przekazywane jako parametry konstruktora żądań.
- Bufory nie są już używane.
W tej sekcji omówimy nowe metody i pokazujemy, jak działają.
Pobierz miejsce według identyfikatora
Użyj pola fetchPlace()
, aby uzyskać szczegółowe informacje o konkretnym miejscu. fetchPlace()
działa podobnie jak getPlaceById()
.
Aby pobrać miejsce, wykonaj te czynności:
Wywołaj
fetchPlace()
, przekazując obiektFetchPlaceRequest
z określonym identyfikatorem 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.NAME); // Construct a request object, passing the place ID and fields array. FetchPlaceRequest request = FetchPlaceRequest.builder(placeId, placeFields) .build();
Wywołaj
addOnSuccessListener()
, aby obsłużyćFetchPlaceResponse
. Zwracany jest pojedynczy wynikPlace
.// 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()); } });
Pobierz zdjęcie miejsca
Użyj fetchPhoto()
, aby uzyskać zdjęcie miejsca. fetchPhoto()
zwraca zdjęcia wybranego miejsca. Wzór prośby o zdjęcie został uproszczony. Możesz teraz wysyłać żądania PhotoMetadata
bezpośrednio z obiektu Place
. Osobne żądanie nie jest już konieczne.
Maksymalna szerokość lub wysokość zdjęcia to 1600 pikseli. fetchPhoto()
działa podobnie do getPhoto()
.
Aby pobrać zdjęcia miejsca, wykonaj te czynności:
Skonfiguruj połączenie z:
fetchPlace()
. Pamiętaj, aby w prośbie uwzględnić polePHOTO_METADATAS
:List<Place.Field> fields = Arrays.asList(Place.Field.PHOTO_METADATAS);
Pobierz obiekt Place (w tym przykładzie użyto obiektu
fetchPlace()
, ale możesz też użyćfindCurrentPlace()
):FetchPlaceRequest placeRequest = FetchPlaceRequest.builder(placeId, fields).build();
Dodaj
OnSuccessListener
, aby pobrać metadane zdjęcia z wynikowychPlace
wFetchPlaceResponse
, a następnie użyj powstałych metadanych zdjęcia, aby uzyskać bitmapę i tekst źródła: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 z lokalizacji użytkownika
Użyj narzędzia findCurrentPlace()
, aby znaleźć bieżącą lokalizację urządzenia użytkownika. findCurrentPlace()
zwraca listę wartości PlaceLikelihood
wskazujących miejsca, w których prawdopodobnie znajduje się urządzenie użytkownika. findCurrentPlace()
działa podobnie do getCurrentPlace()
.
Aby sprawdzić bieżącą lokalizację urządzenia użytkownika, wykonaj te czynności:
Upewnij się, że aplikacja prosi o przyznanie uprawnień
ACCESS_FINE_LOCATION
iACCESS_WIFI_STATE
. Użytkownik musi przyznać dostęp do bieżącej lokalizacji swojego urządzenia. Więcej informacji znajdziesz w sekcji dotyczącej prośby o uprawnienia aplikacji.Utwórz
FindCurrentPlaceRequest
z 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();
Wywołaj opcję FindCurrentPlace i przetwarzaj 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żywaj funkcji findAutocompletePredictions()
, aby zwracać prognozy miejsc w odpowiedzi na zapytania użytkowników.
findAutocompletePredictions()
działa podobnie do getAutocompletePredictions()
.
Ten przykład przedstawia wywołanie metody 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ę w celach rozliczeniowych. Zalecamy używanie tokenów sesji we wszystkich sesjach autouzupełniania. Sesja rozpoczyna się, gdy użytkownik zaczyna wpisywać zapytanie, a kończy, gdy wybierze miejsce. Każda sesja może obejmować wiele zapytań, po których następuje wybór jednego miejsca. Po zakończeniu sesji token jest nieważny. Aplikacja musi wygenerować nowy token dla każdej sesji.
Maski pól
W metodach, które zwracają informacje o miejscach, musisz określić typy danych o miejscach, które mają być zwracane w przypadku każdego żądania. Dzięki temu możesz mieć pewność, że żądasz (i płacisz) tylko tych danych, których rzeczywiście używasz.
Aby określić, które typy danych mają być zwracane, przekaż tablicę Place.Field
w 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
Dowiedz się więcej o kodach SKU danych Miejsc.
Aktualizacje selektora miejsc i autouzupełniania
W tej sekcji opisujemy zmiany wprowadzone w widżetach Miejsc (Selektor miejsc i Autouzupełnianie).
Autouzupełnianie
W autouzupełnianiu wprowadzono te zmiany:
- Nazwa sieci
PlaceAutocomplete
została zmieniona naAutocomplete
.- Nazwa sieci
PlaceAutocomplete.getPlace
została zmieniona naAutocomplete.getPlaceFromIntent
. - Nazwa sieci
PlaceAutocomplete.getStatus
została zmieniona naAutocomplete.getStatusFromIntent
.
- Nazwa sieci
- Nazwa elementu
PlaceAutocomplete.RESULT_ERROR
została zmieniona naAutocompleteActivity.RESULT_ERROR
(obsługa błędów fragmentu autouzupełniania NIE uległa zmianie).
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 korzystanie z nich spowoduje wyświetlenie komunikatu o błędzie. Nowy pakiet SDK nie obsługuje selektora miejsc.
Autouzupełnianie widżetów
Zaktualizowano widżety autouzupełniania:
- 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, co pozwala wybrać typy danych o miejscach, które mają być zwracane po dokonaniu wyboru przez użytkownika.
Z sekcji poniżej dowiesz się, jak dodać do projektu widżet autouzupełniania.
Umieszczanie obiektu AutocompleteFragment
Aby dodać fragment autouzupełniania, wykonaj następujące czynności:
Dodaj fragment do układu XML aktywności, jak pokazano w poniższym 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" />
Aby dodać widżet autouzupełniania do aktywności, wykonaj te czynności:
- Zainicjuj
Places
, przekazując kontekst aplikacji i swój klucz interfejsu API. - Zainicjuj plik
AutocompleteSupportFragment
. - Wywołaj
setPlaceFields()
, aby wskazać typy danych o miejscach, które chcesz uzyskać. - Dodaj
PlaceSelectionListener
, aby wykonać działanie z wynikiem i obsługiwać ewentualne błędy.
Ten przykład pokazuje dodawanie widżetu autouzupełniania do działania:
/** * 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); } });
- Zainicjuj
Używaj intencji do uruchomienia działania autouzupełniania
- Zainicjuj
Places
, przekazując kontekst aplikacji i klucz interfejsu API - Użyj
Autocomplete.IntentBuilder
, aby utworzyć intencję przekazującą wybrany trybPlaceAutocomplete
(pełny ekran lub nakładka). Intencja musi wywołaćstartActivityForResult
, przekazując kod żądania, który identyfikuje Twój zamiar. - Zastąp wywołanie zwrotne
onActivityResult
dotyczące wybranego miejsca.
Z przykładu poniżej dowiesz się, jak za pomocą intencji uruchomić autouzupełnianie, 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.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 korzystanie z nich spowoduje wyświetlenie komunikatu o błędzie. Nowy pakiet SDK nie obsługuje selektora miejsc.