Переход на новый клиент 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.
  • Есть совершенно новые методы .
  • Маски полей теперь поддерживаются для методов, возвращающих сведения о месте. Вы можете использовать маски полей, чтобы указать, какие типы данных о местах следует возвращать.
  • Улучшены коды состояния, используемые для сообщения об ошибках.
  • Автозаполнение теперь поддерживает токены сеанса .
  • Средство выбора мест больше недоступно .

О библиотеке совместимости с Google Адресами

В январе 2019 года, выпустив версию 1.0 автономного Places SDK для Android, Google предоставила библиотеку совместимости, которая поможет при переходе с выведенной из эксплуатации версии Google Play Services Places 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:3.3.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:3.3.0'

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

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

  5. Обновите свои ресурсы «На базе 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);

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

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

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

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

    • Ключ API не предоставлен.
    • Был предоставлен неверный ключ API.
    • API-интерфейс Places не включен в консоли Cloud.
    • Ключ 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.DISPLAY_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 с указанием мест, где с наибольшей вероятностью будет расположено устройство пользователя. 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.DISPLAY_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.FORMATTED_ADDRESS,
                                              Place.Field.ID,
                                              Place.Field.INTERNATIONAL_PHONE_NUMBER);

Список полей, которые можно использовать в маске поля, см. в разделе Размещение полей данных (новое) .

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

    • Инициализируйте 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.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);
        }
    });
    

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

  1. Инициализируйте 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.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.
            }
        }
    }

Средство выбора мест больше недоступно.

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