¿Cómo obtener la ubicación actual en Android?

Como desarrollador, cuando trabaja en ubicaciones en Android, siempre tiene algunas dudas sobre cómo seleccionar el mejor y más eficiente enfoque para sus necesidades. Entonces, en este artículo, vamos a discutir cómo obtener la ubicación actual del usuario en Android. Hay dos formas de obtener la ubicación actual de cualquier dispositivo Android:

  1. API del administrador de ubicación de Android
  2. Proveedor de ubicación fusionada: API de ubicación de servicios de Google Play

Pregunta: ¿Cuál es eficiente y por qué?

Respuesta: Proveedor de ubicación fusionada porque optimiza el uso de energía de la batería del dispositivo.

Antes de mover cualquiera de los métodos anteriores tendremos que pedir permiso de ubicación.

Tomando permiso de ubicación

Paso 1: Defina los permisos de uso para el acceso a la ubicación en el archivo de manifiesto

<!– Para solicitar acceso a la ubicación en primer plano, declare uno de estos permisos. –>

<usos-permiso android:name=”android.permission.ACCESS_FINE_LOCATION” />

<usos-permiso android:name=”android.permission.ACCESS_COARSE_LOCATION” />

<!– Requerido solo cuando se solicita acceso a la ubicación en segundo plano en Android 10 (nivel de API 29) –>

<usos-permiso android:name=”android.permission.ACCESS_BACKGROUND_LOCATION” />

Nota:

Para recibir actualizaciones de ubicación de NETWORK_PROVIDER o GPS_PROVIDER, debe solicitar el permiso del usuario declarando el permiso ACCESS_COARSE_LOCATION o ACCESS_FINE_LOCATION, respectivamente, en su archivo de manifiesto de Android. Sin estos permisos, su aplicación fallará en tiempo de ejecución cuando solicite actualizaciones de ubicación.

Si está utilizando NETWORK_PROVIDER y GPS_PROVIDER, debe solicitar solo el permiso ACCESS_FINE_LOCATION, ya que incluye permisos para ambos proveedores. El permiso para ACCESS_COARSE_LOCATION permite el acceso solo a NETWORK_PROVIDER.

Paso 2: Defina los permisos de uso para el acceso a Internet porque vamos a utilizar el proveedor de Internet.

<usos-permiso android:name=”android.permission.INTERNET”/>

Paso 3: escriba una función para verificar si se otorga o no el permiso de ubicación. Si no se otorga el permiso, solicite los permisos en tiempo de ejecución.

Kotlin

private fun isLocationPermissionGranted(): Boolean {
    return if (ActivityCompat.checkSelfPermission(
            this,
            android.Manifest.permission.ACCESS_COARSE_LOCATION
        ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
            this,
            android.Manifest.permission.ACCESS_FINE_LOCATION
        ) != PackageManager.PERMISSION_GRANTED
    ) {
        ActivityCompat.requestPermissions(
            this,
            arrayOf(
                android.Manifest.permission.ACCESS_FINE_LOCATION,
                android.Manifest.permission.ACCESS_COARSE_LOCATION
            ),
            requestcode
        )
        false
    } else {
        true
    }
}

Ahora, después de manejar los permisos de ubicación, vamos a aprender cómo podemos obtener la ubicación en Android.

Primer método: por la API del administrador de ubicación de Android

Suponemos que al usuario se le ha otorgado permiso de ubicación. Si no, pregunta primero.

Paso 1: crear una instancia de LocationManager en el contexto de LOCATION_SERVICE.

Kotlin

private var currentLocation: Location? = null
lateinit var locationManager: LocationManager
locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager

Paso 2: Comprueba que si el GPS y la red están disponibles o no y si ambos están disponibles, usamos uno con mayor precisión.

Kotlin

val hasGps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
//------------------------------------------------------//
val hasNetwork = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)

Paso 3: Crear una instancia de LocationListener (paquete: android.location) para ambos (GPS y Red).

Kotlin

val gpsLocationListener: LocationListener = object : LocationListener {
    override fun onLocationChanged(location: Location) {
        locationByGps= location
    }
  
    override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {}
    override fun onProviderEnabled(provider: String) {}
    override fun onProviderDisabled(provider: String) {}
}
//------------------------------------------------------//
val networkLocationListener: LocationListener = object : LocationListener {
    override fun onLocationChanged(location: Location) {
        locationByNetwork= location
    }
  
    override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {}
    override fun onProviderEnabled(provider: String) {}
    override fun onProviderDisabled(provider: String) {}
}

Paso 4: si alguno de los proveedores de red o GPS está habilitado, solicitaremos una actualización de ubicación actual desde LocationManager con LocationListener.

Kotlin

if (hasGps) {
    locationManager.requestLocationUpdates(
        LocationManager.GPS_PROVIDER,
        5000,
        0F,
        gpsLocationListener
    )
}
//------------------------------------------------------//
if (hasNetwork) {
    locationManager.requestLocationUpdates(
        LocationManager.NETWORK_PROVIDER,
        5000,
        0F,
        networkLocationListener
    )
}

Paso 5: Ahora verificamos qué proveedor nos ha dado la ubicación más precisa y luego usaremos esa ubicación según nuestros requisitos.

Kotlin

val lastKnownLocationByGps =
  locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)
lastKnownLocationByGps?.let {
    locationByGps = lastKnownLocationByGps
}
//------------------------------------------------------//
val lastKnownLocationByNetwork =
  locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)
lastKnownLocationByNetwork?.let {
    locationByNetwork = lastKnownLocationByNetwork
}
//------------------------------------------------------//
if (locationByGps != null && locationByNetwork != null) {
    if (locationByGps.accuracy > locationByNetwork!!.accuracy) {
        currentLocation = locationByGps
        latitude = currentLocation.latitude
        longitude = currentLocation.longitude
        // use latitude and longitude as per your need
    } else {
        currentLocation = locationByNetwork
        latitude = currentLocation.latitude
        longitude = currentLocation.longitude
        // use latitude and longitude as per your need
    }
}

Ahora, después de aprender cómo podemos obtener la ubicación en Android mediante la API del Administrador de ubicación, nos movemos al segundo método Proveedor de ubicación fusionada (API de ubicación de servicios de Google Play) .

Segundo método: por proveedor de ubicación fusionada

Suponemos que al usuario se le ha otorgado permiso de ubicación. Si no, pregunta primero. El proveedor de ubicación fusionado son las API de ubicación de los servicios de Google Play. Proporciona una API simple para obtener ubicaciones con precisión alta, media y baja. También optimiza el uso de energía de la batería del dispositivo. Así que deberíamos preferir este método.

Paso 1: declarar variables de FusedLocationProviderClient, LocationRequest, LocationCallback y Location.

Kotlin

// FusedLocationProviderClient - Main class for receiving location updates.
private lateinit var fusedLocationProviderClient: FusedLocationProviderClient
  
// LocationRequest - Requirements for the location updates, i.e.,
// how often you should receive updates, the priority, etc.
private lateinit var locationRequest: LocationRequest
  
// LocationCallback - Called when FusedLocationProviderClient
// has a new Location
private lateinit var locationCallback: LocationCallback
  
// This will store current location info
private var currentLocation: Location? = null

Paso 2: inicialice fusedLocationProviderClient.

Kotlin

fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)

Paso 3: Inicialice la solicitud de ubicación.

Kotlin

locationRequest = LocationRequest().apply {
    // Sets the desired interval for
      // active location updates. 
      // This interval is inexact.
    interval = TimeUnit.SECONDS.toMillis(60)
  
    // Sets the fastest rate for active location updates. 
     // This interval is exact, and your application will never
      // receive updates more frequently than this value
    fastestInterval = TimeUnit.SECONDS.toMillis(30)
  
    // Sets the maximum time when batched location 
      // updates are delivered. Updates may be
      // delivered sooner than this interval
    maxWaitTime = TimeUnit.MINUTES.toMillis(2)
  
    priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}

Paso 4: Inicializar locationCallback.

Kotlin

locationCallback = object : LocationCallback() {
    override fun onLocationResult(locationResult: LocationResult?) {
        super.onLocationResult(locationResult)
        locationResult?.lastLocation?.let {
            currentLocation = locationByGps
            latitude = currentLocation.latitude
            longitude = currentLocation.longitude
            // use latitude and longitude as per your need
        } ?: {
            Log.d(TAG, "Location information isn't available.")
        }
    }
}

Paso 5: ahora que inicializó todo, debe informar a FusedLocationProviderClient que desea recibir actualizaciones. Así que suscríbete a los cambios de ubicación.

Kotlin

fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper())

Paso 6: cuando la aplicación ya no necesite acceder a la información de ubicación, es importante darse de baja de las actualizaciones de ubicación.

Kotlin

val removeTask = fusedLocationProviderClient.removeLocationUpdates(locationCallback)
removeTask.addOnCompleteListener { task ->
   if (task.isSuccessful) {
       Log.d(TAG, "Location Callback removed.")
   } else {
       Log.d(TAG, "Failed to remove Location Callback.")
   }
}

Ahora un punto más importante para brindar soporte para Android 10 y Android R. Así que hablemos de eso…

Soporte para Android 10

Paso 1: Realice estos cambios en el archivo build.gradle .

  1. Establezca compileSdkVersion en 29.
  2. Establezca buildToolsVersion en «29.0.3».
  3. Establezca targetSdkVersion en 29.

Su código debería ser algo como esto:

android {

  compileSdkVersión 29

  buildToolsVersión «29.0.3»

  configuración por defecto {

      applicationId «com.example.android.ubicación»

      minSdk Versión 26

      targetSdkVersión 29

      código de versión 1

      nombre de la versión «1.0»

  }

}

Paso 2: si tiene un servicio en primer plano, declare un tipo de ubicación en primer plano en el manifiesto.

android:foregroundServiceType=”ubicación”

Su código debería ser algo como esto:

<aplicación>

   …

   <!– Los servicios de primer plano en Android 10+ requieren tipo. –>

   <servicio

android:name=”com.example.android.ubicación.ForegroundOnlyLocationService”

       Android: habilitado = «verdadero»

       Android: exportado = «falso»

       android:foregroundServiceType=”ubicación” />

</aplicación>

Soporte para Android 11 o Android R

¡Buenas noticias, no necesita hacer cambios en ningún archivo, excepto en el archivo build.gradle! Haz estos cambios:

  1. compileSdkVersion a «android-R»
  2. targetSdkVersion a «R»

Su código debería ser algo como esto:

android {

  compileSdkVersion «android-R»

  buildToolsVersión «29.0.2»

  configuración por defecto {

      applicationId «com.example.android.ubicación»

      minSdk Versión 26

      targetSdkVersión «R»

      código de versión 1

      nombre de la versión «1.0»

  }

}

Publicación traducida automáticamente

Artículo escrito por sachankapil y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *