Переход на новый клиент Places SDK

Оптимизируйте свои подборки Сохраняйте и классифицируйте контент в соответствии со своими настройками.

В этом руководстве объясняются различия между библиотекой совместимости Places и новой автономной версией Places SDK для Android . Если вы использовали библиотеку совместимости Places вместо перехода на новую автономную версию Places SDK для Android, в этом руководстве показано, как обновить проекты, чтобы использовать новую версию Places SDK для Android.

Единственный способ получить доступ к функциям и исправлениям ошибок в Places SDK для Android выше версии 2.6.0 — использовать Places SDK для Android. Google рекомендует как можно скорее обновить библиотеку совместимости до новой версии Places SDK для Android.

Что изменилось?

Основные направления изменений следующие:

  • Новая версия Places SDK для Android распространяется в виде статической клиентской библиотеки. До января 2019 года Places SDK для Android был доступен через сервисы Google Play. С тех пор была предоставлена ​​библиотека совместимости Places, чтобы упростить переход на новый Places SDK для Android.
  • Есть совершенно новые методы .
  • Маски полей теперь поддерживаются для методов, возвращающих сведения о месте. Вы можете использовать маски полей, чтобы указать, какие типы данных о местах следует возвращать.
  • Коды состояния, используемые для сообщения об ошибках, были улучшены.
  • Автозаполнение теперь поддерживает токены сеанса .
  • Средство выбора мест больше недоступно .

О библиотеке совместимости Places

В январе 2019 г. с выпуском версии 1.0 автономного SDK Places для Android компания Google предоставила библиотеку совместимости, чтобы помочь с миграцией с выведенной из эксплуатации версии Google Play Services SDK для Android ( com.google.android.gms:play-services-places ).

Эта библиотека совместимости была временно предоставлена ​​для перенаправления и преобразования вызовов API, направленных на версию сервисов Google Play, в новую автономную версию, пока разработчики не смогут перенести свой код для использования новых имен в автономном SDK. Для каждой версии Places SDK для Android, начиная с версии 1.0 и заканчивая версией 2.6.0, была выпущена соответствующая версия библиотеки совместимости Places, обеспечивающая эквивалентную функциональность.

Замораживание и прекращение поддержки библиотеки совместимости Places

Все версии библиотеки совместимости для Places SDK для Android устарели с 31 марта 2022 г. Версия 2.6.0 — это последняя версия библиотеки совместимости Places. Единственный способ получить доступ к функциям и исправлениям ошибок в Places SDK для Android выше версии 2.6.0 — использовать Places SDK для Android.

Google рекомендует перейти на Places SDK для Android, чтобы получить доступ к новым функциям и исправлениям критических ошибок в выпусках выше версии 2.6.0. Если вы в настоящее время используете библиотеку совместимости, выполните действия, описанные ниже в разделе « Установка Places SDK для Android », чтобы перейти на Places SDK для Android.

Установите клиентскую библиотеку

Новая версия Places SDK для Android распространяется в виде статической клиентской библиотеки.

Используйте Maven , чтобы добавить Places SDK для Android в свой проект Android Studio:

  1. Если вы в настоящее время используете библиотеку совместимости Places :

    1. Замените следующую строку в разделе dependencies :

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

      С помощью этой строки переключитесь на Places SDK для Android:

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

  2. Если в настоящее время вы используете версию Places SDK для Android в Play Services :

    1. Замените следующую строку в разделе dependencies :

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

      С помощью этой строки переключитесь на Places SDK для Android:

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

  3. Синхронизируйте свой проект Gradle.

  4. Установите minSdkVersion для вашего проекта приложения на 16 или выше.

  5. Обновите свои активы "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. Создайте свое приложение. Если вы видите какие-либо ошибки сборки из-за перехода на Places SDK для Android, см. разделы ниже для получения информации об устранении этих ошибок.

Инициализировать новый клиент Places SDK

Инициализируйте новый клиент Places SDK, как показано в следующем примере:

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

Коды состояния

Код состояния для ошибок ограничения количества запросов в секунду изменился. Ошибки лимита количества запросов в секунду теперь возвращаются через PlaceStatusCodes.OVER_QUERY_LIMIT . Ограничений QPD больше нет.

Добавлены следующие коды состояния:

  • REQUEST_DENIED — запрос отклонен. Возможные причины этого включают:

    • Ключ API не был предоставлен.
    • Был предоставлен неверный ключ API.
    • API Places не был включен в облачной консоли.
    • Ключ API был предоставлен с неправильными ограничениями ключа.
  • INVALID_REQUEST — запрос недействителен из-за отсутствующего или недопустимого аргумента.

  • NOT_FOUND — По данному запросу не найдено ни одного результата.

Новые методы

В новой версии Places SDK для Android представлены совершенно новые методы, разработанные для единообразия. Все новые методы придерживаются следующего:

  • Конечные точки больше не используют глагол get .
  • Объекты запроса и ответа имеют то же имя, что и соответствующий клиентский метод.
  • Объекты запроса теперь имеют строителей; обязательные параметры передаются как параметры построителя запроса.
  • Буферы больше не используются.

В этом разделе представлены новые методы и показано, как они работают.

Получить место по идентификатору

Используйте fetchPlace() , чтобы получить информацию о конкретном месте. fetchPlace() аналогична функции getPlaceById() .

Чтобы выбрать место, выполните следующие действия:

  1. Вызовите fetchPlace() , передав объект FetchPlaceRequest с указанием идентификатора места и списка полей , указывающих возвращаемые данные места.

    // 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. Вызовите addOnSuccessListener() для обработки FetchPlaceResponse . Возвращается одно 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());
        }
    });
    

Получить фото места

Используйте fetchPhoto() , чтобы получить фотографию места. fetchPhoto() возвращает фотографии места. Шаблон для запроса фотографии был упрощен. Теперь вы можете запрашивать PhotoMetadata непосредственно из объекта Place ; отдельный запрос больше не требуется. Фотографии могут иметь максимальную ширину или высоту 1600 пикселей. fetchPhoto() аналогична функции getPhoto() .

Чтобы получить фотографии мест, выполните следующие действия:

  1. Настройте вызов fetchPlace() . Обязательно включите в запрос поле PHOTO_METADATAS :

    List<Place.Field> fields = Arrays.asList(Place.Field.PHOTO_METADATAS);
    
  2. Получите объект Place (в этом примере используется fetchPlace() , но вы также можете использовать findCurrentPlace() ):

    FetchPlaceRequest placeRequest = FetchPlaceRequest.builder(placeId, fields).build();
    
  3. Добавьте OnSuccessListener , чтобы получить метаданные фотографии из результирующего Place в FetchPlaceResponse , а затем используйте полученные метаданные фотографии, чтобы получить растровое изображение и текст атрибуции:

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

Найти место по местоположению пользователя

Используйте findCurrentPlace() , чтобы найти текущее местоположение устройства пользователя. findCurrentPlace() возвращает список PlaceLikelihood s, указывающих места, где наиболее вероятно будет находиться устройство пользователя. findCurrentPlace() аналогична функции getCurrentPlace() .

Выполните следующие действия, чтобы получить текущее местоположение устройства пользователя:

  1. Убедитесь, что ваше приложение запрашивает разрешения ACCESS_FINE_LOCATION и ACCESS_WIFI_STATE . Пользователь должен предоставить разрешение на доступ к своему текущему местоположению устройства. Дополнительные сведения см. в разделе Запрос разрешений для приложений .

  2. Создайте FindCurrentPlaceRequest , включая список возвращаемых типов данных места.

      // 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. Вызовите findCurrentPlace и обработайте ответ, предварительно проверив, что пользователь предоставил разрешение на использование местоположения своего устройства.

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

Найдите подсказки автозаполнения

Используйте findAutocompletePredictions() , чтобы возвращать прогнозы мест в ответ на поисковые запросы пользователей. findAutocompletePredictions() аналогична функции getAutocompletePredictions() .

В следующем примере показан вызов 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());
   }
});

Токены сеанса

Маркеры сеанса группируют этапы запроса и выбора пользовательского поиска в отдельный сеанс для целей выставления счетов. Мы рекомендуем использовать токены сеанса для всех сеансов автозаполнения. Сеанс начинается, когда пользователь начинает вводить запрос, и завершается, когда он выбирает место. Каждый сеанс может иметь несколько запросов, за которыми следует выбор одного места. После завершения сеанса токен больше не действителен; ваше приложение должно генерировать новый токен для каждого сеанса.

Полевые маски

В методах, которые возвращают сведения о месте, необходимо указать, какие типы данных о месте следует возвращать с каждым запросом. Это помогает гарантировать, что вы запрашиваете (и оплачиваете) только те данные, которые действительно будете использовать.

Чтобы указать, какие типы данных возвращать, передайте массив Place.Field в FetchPlaceRequest , как показано в следующем примере:

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

Вы можете использовать одно или несколько из следующих полей:

  • 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

Узнайте больше о SKU Places Data .

Обновления средства выбора места и автозаполнения

В этом разделе объясняются изменения в виджетах «Места» («Выбор мест» и «Автозаполнение»).

Программное автозаполнение

В автозаполнение внесены следующие изменения:

  • PlaceAutocomplete переименован в Autocomplete .
    • PlaceAutocomplete.getPlace переименован в Autocomplete.getPlaceFromIntent .
    • PlaceAutocomplete.getStatus переименован в Autocomplete.getStatusFromIntent .
  • PlaceAutocomplete.RESULT_ERROR переименован в AutocompleteActivity.RESULT_ERROR (обработка ошибок для фрагмента автозаполнения НЕ изменилась).

Выбор места

Средство выбора места устарело 29 января 2019 г. Оно было отключено 29 июля 2019 г. и больше недоступно. Дальнейшее использование приведет к появлению сообщения об ошибке. Новый SDK не поддерживает средство выбора мест.

Виджеты автозаполнения

Обновлены виджеты автозаполнения:

  • Префикс Place удален из всех классов.
  • Добавлена ​​поддержка токенов сеанса. Виджет автоматически управляет токенами в фоновом режиме.
  • Добавлена ​​поддержка масок полей, которые позволяют вам выбирать, какие типы данных места возвращать после того, как пользователь сделает выбор.

В следующих разделах показано, как добавить в проект виджет автозаполнения.

Встроить AutocompleteFragment

Чтобы добавить фрагмент автозаполнения, выполните следующие действия:

  1. Добавьте фрагмент в XML-макет своей активности, как показано в следующем примере.

    <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. Чтобы добавить виджет автозаполнения в активность, выполните следующие действия:

    • Initialize Places , передав контекст приложения и ваш ключ API.
    • Инициализируйте AutocompleteSupportFragment .
    • Вызовите setPlaceFields() , чтобы указать типы данных о местах, которые вы хотите получить.
    • Добавьте PlaceSelectionListener , чтобы что-то делать с результатом, а также обрабатывать любые ошибки, которые могут возникнуть.

    В следующем примере показано добавление виджета автозаполнения к действию:

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

Используйте намерение для запуска действия автозаполнения

  1. Initialize Places , передав контекст приложения и ваш ключ API
  2. Используйте Autocomplete.IntentBuilder , чтобы создать намерение, передав нужный режим PlaceAutocomplete (полноэкранный режим или наложение). Намерение должно вызывать startActivityForResult , передавая код запроса, идентифицирующий ваше намерение.
  3. Переопределите обратный вызов onActivityResult , чтобы получить выбранное место.

В следующем примере показано, как использовать намерение для запуска автозаполнения, а затем обрабатывать результат:

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

Выбор мест больше не доступен

Средство выбора места устарело 29 января 2019 г. Оно было отключено 29 июля 2019 г. и больше недоступно. Дальнейшее использование приведет к появлению сообщения об ошибке. Новый SDK не поддерживает средство выбора мест.