Cómo cambiar la configuración de la ubicación

Si tu app necesita solicitar una ubicación o recibir actualizaciones de permisos, el dispositivo debe tener habilitada la configuración del sistema apropiada, como la búsqueda de Wi-Fi o GPS. En lugar de habilitar directamente servicios como el GPS del dispositivo, tu app especifica el nivel requerido de consumo de energía o precisión y el intervalo de actualización deseado, y el dispositivo hace los cambios apropiados en la configuración del sistema automáticamente. El objeto de datos LocationRequest define estos parámetros de configuración.

En esta lección, aprenderás cómo usar el Cliente de configuración para verificar qué parámetros están habilitados y cómo mostrarle el diálogo "configuración de la ubicación" al usuario para que actualice su configuración con un solo toque.

Cómo configurar los servicios de ubicación

A fin de usar los servicios de ubicación que proporcionan los Servicios de Google Play y el proveedor de ubicación combinada, conecta la app mediante el Cliente de configuración y, luego, comprueba la configuración de la ubicación actual y pídele al usuario que habilite la configuración obligatoria si es necesario.

Las apps que usan los servicios de ubicación deben solicitar permisos de ubicación. Para esta lección, la detección de ubicación aproximada es suficiente. Solicita este permiso con el elemento uses-permission en el manifiesto de tu app, como se muestra en el ejemplo que aparece a continuación:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.google.android.gms.location.sample.locationupdates" >

      <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    </manifest>
    

Si el dispositivo tiene instalado Android 6.0 o versiones posteriores, y el SDK de destino de tu app es 23 o superior, la app debe incluir una lista de los permisos en el manifiesto y solicitar esos permisos durante el tiempo de ejecución. Para obtener más información, consulta Cómo solicitar permisos durante el tiempo de ejecución.

Si tu app se orienta a Android 10 (API nivel 29) o versiones posteriores y necesita acceder a la ubicación el dispositivo mientras está en segundo plano, también debes declarar el permiso de ACCESS_BACKGROUND_LOCATION. Para obtener más información, consulta la sección sobre cómo solicitar acceso a la ubicación en segundo plano.

Cómo configurar una solicitud de ubicación

Si deseas almacenar los parámetros de solicitudes en el proveedor de ubicación combinada, crea una LocationRequest. Los parámetros determinan el nivel de precisión de las solicitudes de ubicación. Para obtener detalles sobre todas las opciones de solicitud de ubicación disponibles, consulta la referencia de la clase LocationRequest. En esta lección, aprenderás cómo definir el intervalo de actualización, el intervalo de actualización más rápido y la prioridad, como se describe a continuación:

Intervalo de actualización
setInterval() Este método define en milésimas de segundos la tasa a la que tu app prefiere recibir actualizaciones de ubicación. Ten en cuenta que las actualizaciones de ubicación pueden ser más rápidas o más lentas que esta tasa a fin de optimizar el uso de batería, o quizás no haya actualizaciones en absoluto (por ejemplo, si el dispositivo no tiene conectividad).
Intervalo de actualización más rápido
setFastestInterval() Este método define en milésimas de segundos la tasa más rápida a la que tu app puede controlar las actualizaciones de ubicación. A menos que a tu app le convenga recibir actualizaciones más rápido que la tasa especificada en setInterval(), no necesitas llamar a este método.
Prioridad

setPriority() Este método define la prioridad de la solicitud, lo que les indica a los servicios de ubicación de Servicios de Google Play qué fuentes de ubicación deben usar. Se admiten los siguientes valores:

  • PRIORITY_BALANCED_POWER_ACCURACY Usa esta configuración para solicitar precisión de ubicación de hasta una manzana, lo que equivale a aproximadamente 100 metros. Este nivel de precisión se considera aproximado y es probable que consuma menos energía. Con esta configuración, es probable que los servicios de ubicación usen el posicionamiento de torres de telefonía celular y Wi-Fi. Sin embargo, ten en cuenta que la elección del proveedor de ubicación depende de muchos factores, como de las fuentes que están disponibles.
  • PRIORITY_HIGH_ACCURACY Usa esta configuración para solicitar la ubicación más precisa posible. Con esta configuración, es más probable que los servicios de ubicación usen GPS para determinar la ubicación.
  • PRIORITY_LOW_POWER Usa esta configuración para solicitar precisión a nivel de la ciudad, lo que equivale a una precisión de aproximadamente 10 kilómetros. Este nivel de precisión se considera aproximado y es probable que consuma menos energía.
  • PRIORITY_NO_POWER Usa esta configuración si necesitas que el impacto en el consumo de energía sea insignificante, pero deseas recibir actualizaciones de ubicación cuando estén disponibles. Con esta configuración, tu app no activa actualizaciones de ubicación, pero sí recibe ubicaciones activadas por otras apps.

Crea la solicitud de ubicación y define los parámetros como se muestra en el siguiente código de ejemplo:

Kotlin

    fun createLocationRequest() {
        val locationRequest = LocationRequest.create()?.apply {
            interval = 10000
            fastestInterval = 5000
            priority = LocationRequest.PRIORITY_HIGH_ACCURACY
        }
    }
    

Java

    protected void createLocationRequest() {
        LocationRequest locationRequest = LocationRequest.create();
        locationRequest.setInterval(10000);
        locationRequest.setFastestInterval(5000);
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }
    

La prioridad de PRIORITY_HIGH_ACCURACY, junto con la configuración de permiso de ACCESS_FINE_LOCATION que definiste en el manifiesto de la app y un intervalo de actualización rápido de 5,000 milésimas de segundos (5 segundos), permite que el proveedor de ubicación combinada muestre actualizaciones de ubicación con una precisión de hasta unos pocos metros. Este enfoque es el apropiado para mapear apps que muestran la ubicación en tiempo real.

Sugerencia de rendimiento: Si tu app accede a la red o realiza otro trabajo de ejecución prolongada después de recibir una actualización de ubicación, ajusta el intervalo más rápido a un valor inferior. Este ajuste evita que la app reciba actualizaciones que no puede usar. Una vez que se haya completado el trabajo de ejecución prolongada, vuelve a establecer el intervalo más rápido en un valor rápido.

Cómo obtener la configuración de la ubicación actual

Una vez que te hayas conectado a los Servicios de Google Play y la API de servicios de ubicación, puedes obtener la configuración de la ubicación actual del dispositivo de un usuario. Para ello, crea un LocationSettingsRequest.Builder y agrega una o más solicitudes de ubicación. En el siguiente fragmento de código, se muestra cómo agregar la solicitud de ubicación que se creó en el paso anterior:

Kotlin

    val builder = LocationSettingsRequest.Builder()
            .addLocationRequest(locationRequest)
    

Java

    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
         .addLocationRequest(locationRequest);
    

A continuación, verifica que se cumpla la configuración de la ubicación actual:

Kotlin

    val builder = LocationSettingsRequest.Builder()

    // ...

    val client: SettingsClient = LocationServices.getSettingsClient(this)
    val task: Task<LocationSettingsResponse> = client.checkLocationSettings(builder.build())
    

Java

    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();

    // ...

    SettingsClient client = LocationServices.getSettingsClient(this);
    Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build());
    

Cuando se completa la Task, tu app puede verificar la configuración de la ubicación si observa el código de estado del objeto LocationSettingsResponse. Para obtener incluso más detalles sobre el estado actual de la configuración de la ubicación relevante, tu app puede llamar al método getLocationSettingsStates() del objeto LocationSettingsResponse.

Cómo pedirle al usuario que cambie la configuración de la ubicación

Para determinar si la configuración de la ubicación es apropiada para la solicitud de ubicación, agrega un OnFailureListener al objeto Task que valide la configuración de la ubicación. Luego, comprueba si el objeto Exception que se pasó al método onFailure() es una instancia de la clase ResolvableApiException, que indica que se debe cambiar la configuración. A continuación, muestra un diálogo que le pida permiso al usuario para modificar la configuración de la ubicación mediante una llamada a startResolutionForResult().

En el siguiente fragmento de código, se muestra cómo determinar si la configuración de la ubicación del usuario permite que los servicios de ubicación creen una LocationRequest, además de cómo pedirle permiso al usuario para cambiar la configuración de la ubicación si es necesario:

Kotlin

    task.addOnSuccessListener { locationSettingsResponse ->
        // All location settings are satisfied. The client can initialize
        // location requests here.
        // ...
    }

    task.addOnFailureListener { exception ->
        if (exception is ResolvableApiException){
            // Location settings are not satisfied, but this can be fixed
            // by showing the user a dialog.
            try {
                // Show the dialog by calling startResolutionForResult(),
                // and check the result in onActivityResult().
                exception.startResolutionForResult(this@MainActivity,
                        REQUEST_CHECK_SETTINGS)
            } catch (sendEx: IntentSender.SendIntentException) {
                // Ignore the error.
            }
        }
    }
    

Java

    task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
        @Override
        public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
            // All location settings are satisfied. The client can initialize
            // location requests here.
            // ...
        }
    });

    task.addOnFailureListener(this, new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            if (e instanceof ResolvableApiException) {
                // Location settings are not satisfied, but this can be fixed
                // by showing the user a dialog.
                try {
                    // Show the dialog by calling startResolutionForResult(),
                    // and check the result in onActivityResult().
                    ResolvableApiException resolvable = (ResolvableApiException) e;
                    resolvable.startResolutionForResult(MainActivity.this,
                            REQUEST_CHECK_SETTINGS);
                } catch (IntentSender.SendIntentException sendEx) {
                    // Ignore the error.
                }
            }
        }
    });
    

En la siguiente lección, Cómo recibir actualizaciones de ubicación, aprenderás cómo recibir actualizaciones de ubicación periódicas.