Cómo migrar al cliente del nuevo SDK de Places

En esta guía, se explican los cambios entre la capa de recursos biblioteca de compatibilidad y la nueva versión independiente del SDK de Places para Android. Si usaste la biblioteca de compatibilidad de Places en lugar de migrar la nueva versión independiente del SDK de Places para Android, en esta guía encontrarás cómo actualizar tus proyectos para usar la nueva versión del SDK de Places para Android.

La única forma de acceder a las funciones y correcciones de errores del SDK de Places para Android anterior a la versión 2.6.0 será usar el SDK de Places para Android. Google recomienda actualizar la biblioteca de compatibilidad a la nueva la versión del SDK de Places para Android lo antes posible.

¿Qué cambió?

Las principales áreas de cambio son las siguientes:

  • Se distribuye la nueva versión del SDK de Places para Android como una biblioteca cliente estática. Antes de enero de 2019, el SDK de Places para Android se puso a disposición a través de los Servicios de Google Play. Desde entonces, una empresa de compatibilidad de datos para facilitar la transición al nuevo SDK de Places para Android.
  • Existen métodos completamente nuevos.
  • Las máscaras de campo ahora son compatibles con los métodos que devuelven lugares más detalles. Puedes usar máscaras de campo para especificar los tipos de datos de lugar que deseas el resultado.
  • Se mejoraron los códigos de estado que se utilizan para informar errores.
  • El autocompletado ahora admite tokens de sesión.
  • El Selector de lugares ya no está disponible.

Información acerca de la biblioteca de compatibilidad de Places

En enero de 2019, con el lanzamiento de la versión 1.0 del SDK de Places para Android independiente, Google proporcionó una biblioteca de compatibilidad para ayudar con la migración. de la versión retirada de servicio de Google Play Services del SDK de Places para Android (com.google.android.gms:play-services-places).

Se proporcionó temporalmente esta biblioteca de compatibilidad para redireccionar y traducir Llamadas a la API dirigidas a la versión de los Servicios de Google Play a la nueva versión independiente hasta que los desarrolladores pudieran migrar su código para usar los nuevos nombres en la SDK independiente. Para cada versión del SDK de Places para Android que desde la versión 1.0 hasta la 2.6.0, la versión correspondiente de la biblioteca de compatibilidad de Places para brindar funcionalidad.

Inmovilización y baja de la biblioteca de compatibilidad de Places

Todas las versiones de la biblioteca de compatibilidad del SDK de Places para Android se dieron de baja a partir del 31 de marzo de 2022. La versión 2.6.0 es la última versión de la Biblioteca de compatibilidad de Places. La única forma de acceder a las funciones y correcciones de errores de Places Se usará el SDK de Places para Android a partir de la versión 2.6.0.

Google recomienda que migres al SDK de Places para Android. para acceder a nuevas funciones y correcciones de errores críticos de las versiones anteriores a la versión 2.6.0. Si actualmente usas la biblioteca de compatibilidad, sigue los pasos que se indican a continuación en Instala la sección del SDK de Places para Android para realizar la migración. con el SDK de Places para Android.

Instala la biblioteca cliente

La nueva versión del SDK de Places para Android se distribuye como un una biblioteca cliente estática.

Usa Maven para agregar Places SDK for Android en tu proyecto de Android Studio:

  1. Si actualmente usas la biblioteca de compatibilidad de Places, haz lo siguiente:

    1. Reemplaza la siguiente línea en la sección dependencies:

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

      Para cambiar al SDK de Places para Android, usa esta línea:

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

  2. Si actualmente usas la versión de Servicios de Play del SDK de Places para Android, haz lo siguiente:

    1. Reemplaza la siguiente línea en la sección dependencies:

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

      Para cambiar al SDK de Places para Android, usa esta línea:

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

  3. Sincroniza tu proyecto de Gradle.

  4. Establece el minSdkVersion del proyecto de aplicación en 16 o una versión posterior.

  5. Actualiza tu cuenta "Con la tecnología de Google" recursos:

    @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. Compila tu app. Si ves algún error de compilación debido a tu conversión a el SDK de Places para Android, consulta las siguientes secciones en resolver estos errores.

Inicializa el nuevo cliente del SDK de Places

Inicializa el nuevo cliente del SDK de Places, como se muestra en el siguiente ejemplo:

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

Códigos de estado

El código de estado de los errores de límite de QPS cambió. Los errores de límite de QPS ahora Se devuelven a través de PlaceStatusCodes.OVER_QUERY_LIMIT. No hay más límites de QPD.

Se agregaron los siguientes códigos de estado:

  • REQUEST_DENIED: Se rechazó la solicitud. A continuación, se detallan algunos de los motivos posibles:

    • No se proporcionó una clave de API.
    • Se proporcionó una clave de API no válida.
    • La API de Places no se habilitó en la consola de Cloud.
    • Se proporcionó una clave de API con restricciones de clave incorrectas.
  • INVALID_REQUEST: La solicitud no es válida debido a que falta o no es válida argumento.

  • NOT_FOUND: No se encontraron resultados para la solicitud proporcionada.

Nuevos métodos

En la nueva versión del SDK de Places para Android, se presenta contenido totalmente nuevo de Google, que se diseñaron para ofrecer coherencia. Todos los métodos nuevos cumpla con lo siguiente:

  • Los extremos ya no usan el verbo get.
  • Los objetos Request y Response comparten el mismo nombre que el objeto método de cliente.
  • Los objetos Request ahora tienen compiladores: los parámetros obligatorios se pasan como solicitud parámetros del compilador.
  • Ya no se usan los búferes.

En esta sección, se presentan los métodos nuevos y se muestra cómo funcionan.

Cómo buscar un lugar por ID

Usa fetchPlace(). para obtener detalles sobre un lugar en particular. fetchPlace() funciona de manera similar a getPlaceById()

Sigue estos pasos para recuperar un lugar:

  1. Llama a fetchPlace() pasando un objeto FetchPlaceRequest que especifique un lugar. ID y una lista de campos que especifican los datos de lugar que se mostrarán.

    // 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. Llama a addOnSuccessListener() para controlar FetchPlaceResponse. Un solo Se muestra Place resultado.

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

Obtén una foto de un lugar

Usa fetchPhoto(). para obtener una foto del lugar. fetchPhoto() devuelve fotos de un lugar. El patrón para solicitar una foto se simplificó. Ahora puedes solicitar PhotoMetadata directamente desde el objeto Place ya no es necesaria una solicitud independiente. Las fotos pueden tener un ancho o una altura máximos de 1,600 px. Funciones fetchPhoto() de manera similar a getPhoto().

Sigue estos pasos para recuperar fotos de lugares:

  1. Programa una llamada al fetchPlace(). Asegúrate de incluir el PHOTO_METADATAS en tu solicitud:

    List<Place.Field> fields = Arrays.asList(Place.Field.PHOTO_METADATAS);
    
  2. Obtén un objeto Place (en este ejemplo, se usa fetchPlace(), pero también puedes usar findCurrentPlace()):

    FetchPlaceRequest placeRequest = FetchPlaceRequest.builder(placeId, fields).build();
    
  3. Agrega un elemento OnSuccessListener para obtener los metadatos de la foto del resultado. Place en FetchPlaceResponse y, luego, usa los metadatos de las fotos resultantes para obtén un mapa de bits y texto de atribución:

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

Busca un lugar desde la ubicación del usuario

Usa findCurrentPlace(). para encontrar la ubicación actual del dispositivo del usuario. findCurrentPlace() muestra una lista de objetos PlaceLikelihood que indican los lugares en los que se encuentra el dispositivo del usuario el problema que más probable es que se encuentre. findCurrentPlace() funciona de manera similar a getCurrentPlace()

Sigue estos pasos para obtener la ubicación actual del dispositivo del usuario:

  1. Asegúrate de que tu app solicite ACCESS_FINE_LOCATION y Permisos ACCESS_WIFI_STATE. El usuario debe otorgar permiso para acceder a su ubicación actual del dispositivo. Consulta Solicitar app Permisos para más detalles.

  2. Crea un objeto FindCurrentPlaceRequest, incluida una lista de tipos de datos de lugar para el resultado.

      // 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. Llama a findCurrentPlace y controla la respuesta; primero verifica que el usuario otorgó permiso para usar la ubicación de su dispositivo.

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

Cómo buscar predicciones de autocompletar

Usa findAutocompletePredictions(). para obtener predicciones del sitio en respuesta a las búsquedas de los usuarios. findAutocompletePredictions() funciona de manera similar a getAutocompletePredictions()

En el siguiente ejemplo, se muestra cómo llamar a 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());
   }
});

Tokens de sesión

Los tokens de sesión agrupan las fases de consulta y selección de una búsqueda de usuario en una y discreta para la facturación. Recomendamos usar tokens de sesión para todas las sesiones de autocompletado. La sesión se inicia cuando el usuario comienza a escribir un consulta y concluye cuando selecciona un lugar. Cada sesión puede tener varias consultas, seguidas de una selección de lugar. Una vez finalizada la sesión, el token ya no es válido; tu app debe generar un token nuevo para cada sesión.

Máscaras de campo

En los métodos que devuelven detalles de lugares, debes especificar qué tipos de lugares para mostrar con cada solicitud. Esto ayuda a garantizar que solo solicites (y pagar por) los datos que realmente usarás.

Para especificar qué tipos de datos mostrar, pasa un array de Place.Field en tu FetchPlaceRequest, como se muestra en el siguiente ejemplo:

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

Puedes usar uno o más de los siguientes campos:

  • 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

Obtén más información sobre los SKU de Places Data.

Actualizaciones de Place Picker y Autocomplete

En esta sección, se explican los cambios en los widgets de Places (Place Picker y autocompletar).

Autocompletado programático

Se realizaron los siguientes cambios en la función de autocompletar:

  • El nombre de PlaceAutocomplete cambió por Autocomplete.
    • El nombre de PlaceAutocomplete.getPlace cambió por Autocomplete.getPlaceFromIntent.
    • El nombre de PlaceAutocomplete.getStatus cambió por Autocomplete.getStatusFromIntent.
  • Se cambió el nombre de PlaceAutocomplete.RESULT_ERROR por AutocompleteActivity.RESULT_ERROR. (NO se modificó el manejo de errores para el fragmento de autocompletado).

Seleccionador de sitios

Place Picker dejó de estar disponible el 29 de enero de 2019. Se desactivó el el 29 de julio de 2019 y ya no estará disponible. El uso continuo dará como resultado un mensaje de error. El nuevo SDK no admite el selector de lugares.

Widgets de Autocomplete

Se actualizaron los widgets de autocompletado:

  • Se quitó el prefijo Place de todas las clases.
  • Se agregó compatibilidad con tokens de sesión. El widget administra los tokens por ti automáticamente en segundo plano.
  • Se agregó compatibilidad con máscaras de campo, que permiten elegir los tipos de lugares datos que se devolverán después de que el usuario haga una selección.

En las siguientes secciones, se muestra cómo agregar un widget de Autocomplete a tu proyecto.

Cómo incorporar un AutocompleteFragment

Para agregar un fragmento de Autocomplete, sigue estos pasos:

  1. Agrega un fragmento al diseño XML de tu actividad, como se muestra en el siguiente ejemplo.

    <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. Para agregar el widget de Autocomplete a la actividad, sigue estos pasos:

    • Inicializa Places y pasa el contexto de la aplicación y tu clave de API.
    • Inicializa el objeto AutocompleteSupportFragment.
    • Llama a setPlaceFields() para indicar los tipos de datos de lugar que deseas. para obtener.
    • Agrega un elemento PlaceSelectionListener para realizar una acción con el resultado. para manejar cualquier error que pueda ocurrir.

    En el siguiente ejemplo, se muestra cómo agregar un widget de Autocomplete a una actividad:

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

Usa un intent para iniciar la actividad de autocompletado

  1. Inicializa Places y pasa el contexto de la app y tu clave de API.
  2. Usa Autocomplete.IntentBuilder para crear un intent y pasa los valores deseados Modo PlaceAutocomplete (pantalla completa o superposición) El intent debe llamar startActivityForResult, pasando un código de solicitud que identifique tu .
  3. Anula la devolución de llamada onActivityResult para recibir el lugar seleccionado.

En el siguiente ejemplo, se muestra cómo usar un intent para iniciar el autocompletado. y, luego, manejar el resultado:

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

El selector de lugares ya no está disponible.

Place Picker dejó de estar disponible el 29 de enero de 2019. Se desactivó el el 29 de julio de 2019 y ya no estará disponible. El uso continuo dará como resultado un mensaje de error. El nuevo SDK no admite el selector de lugares.