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:
- API del administrador de ubicación de Android
- 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 .
- Establezca compileSdkVersion en 29.
- Establezca buildToolsVersion en «29.0.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:
- compileSdkVersion a «android-R»
- 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