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:
Jeśli korzystasz z biblioteki zgodności Miejsc:
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'
Jeśli obecnie korzystasz z pakietu SDK Usług na Androida w ramach Usług Google Play:
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'
zsynchronizować projekt Gradle,
Ustaw
minSdkVersion
projektu aplikacji na 16 lub więcej.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
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:
Wywołaj
fetchPlace()
, przekazując obiektFetchPlaceRequest
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();
Wywołaj
addOnSuccessListener()
, aby obsłużyćFetchPlaceResponse
. Zwracany jest jeden 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()); } });
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:
Skonfiguruj połączenie pod numer
fetchPlace()
. Pamiętaj, aby w żądaniu uwzględnić polePHOTO_METADATAS
:List<Place.Field> fields = Arrays.asList(Place.Field.PHOTO_METADATAS);
Pobierz obiekt Place (w tym przykładzie korzystamy z
fetchPlace()
, ale możesz też użyćfindCurrentPlace()
):FetchPlaceRequest placeRequest = FetchPlaceRequest.builder(placeId, fields).build();
Dodaj
OnSuccessListener
, aby pobrać metadane zdjęcia zPlace
wFetchPlaceResponse
, 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:
Upewnij się, że aplikacja prosi o uprawnienia
ACCESS_FINE_LOCATION
iACCESS_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.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();
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 naAutocomplete
.- Nazwa pliku
PlaceAutocomplete.getPlace
została zmieniona naAutocomplete.getPlaceFromIntent
. - Nazwa pliku
PlaceAutocomplete.getStatus
została zmieniona naAutocomplete.getStatusFromIntent
.
- Nazwa pliku
- Nazwa pliku
PlaceAutocomplete.RESULT_ERROR
została zmieniona naAutocompleteActivity.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:
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" />
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); } });
- Inicjuj
Zamiar uruchomienia autouzupełniania
- Inicjowanie
Places
przez przekazanie kontekstu aplikacji i klucza interfejsu API - Użyj metody
Autocomplete.IntentBuilder
, aby utworzyć intencję, przekazując wybrany trybPlaceAutocomplete
(pełny ekran lub nakładka). Intencja musi wywoływać metodęstartActivityForResult
, przekazując kod żądania, który identyfikuje intencję. - 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.