El permiso ACCESS_COARSE_LOCATION proporciona una precisión de torre celular en Android

Estoy haciendo algunas pruebas con la función requestLocationUpdates() de FusedLocationApi . Estoy usando PRIORITY_BALANCED_POWER_ACCURACY . Una precisión de bloque de ciudad está bien para mí.

Cuando solicito el permiso ACCESS_FINE_LOCATION , obtengo una precisión de 100 m, que es genial con GPS desactivado. Como no necesito una precisión de GPS sino una precisión de bloque de ciudad, me gustaría solicitar solo el permiso ACCESS_COARSE_LOCATION . Sin embargo, cuando solicito el permiso ACCESS_COARSE_LOCATION , obtengo una precisión de 2 km. Parece que el dispositivo ya no usa el permiso Wifi y solo una torre de precisión de celda.

¿Cómo puedo tener una mejor precisión con el permiso ACCESS_COARSE_LOCATION ?

Nota: el GPS está desactivado en mi dispositivo de prueba.

Este es un problema interesante, y tenía la impresión de que usar ACCESS_COARSE_LOCATION usaría WiFi, ya que eso es lo que dice la documentación.

La documentación para ACCESS_COARSE_LOCATION indica:

Permite que una aplicación acceda a una ubicación aproximada derivada de las fonts de ubicación de la red, como torres de telefonía móvil y Wi-Fi.

Entonces, lo puse a prueba y los resultados son sorprendentes.

Aquí está el código con el que solía probar:

 public class MainActivity extends Activity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener { LocationRequest mLocationRequest; GoogleApiClient mGoogleApiClient; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); buildGoogleApiClient(); mGoogleApiClient.connect(); } @Override protected void onPause(){ super.onPause(); if (mGoogleApiClient != null) { LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); } } protected synchronized void buildGoogleApiClient() { Toast.makeText(this,"buildGoogleApiClient",Toast.LENGTH_SHORT).show(); mGoogleApiClient = new GoogleApiClient.Builder(this) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build(); } @Override public void onConnected(Bundle bundle) { Toast.makeText(this,"onConnected",Toast.LENGTH_SHORT).show(); mLocationRequest = new LocationRequest(); mLocationRequest.setInterval(10); mLocationRequest.setFastestInterval(10); mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); //mLocationRequest.setPriority(LocationRequest.PRIORITY_LOW_POWER); //mLocationRequest.setSmallestDisplacement(0.1F); LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this); } @Override public void onConnectionSuspended(int i) { Toast.makeText(this,"onConnectionSuspended",Toast.LENGTH_SHORT).show(); } @Override public void onConnectionFailed(ConnectionResult connectionResult) { Toast.makeText(this,"onConnectionFailed",Toast.LENGTH_SHORT).show(); } @Override public void onLocationChanged(Location location) { Log.d("locationtesting", "accuracy: " + location.getAccuracy() + " lat: " + location.getLatitude() + " lon: " + location.getLongitude()); Toast.makeText(this,"Location Changed",Toast.LENGTH_SHORT).show(); } } 

AndroidManifest.xml:

  

build.gradle:

 compile 'com.google.android.gms:play-services:7.3.0' 

La primera prueba que hice fue con PRIORITY_BALANCED_POWER_ACCURACY , y sin WiFi. Tenga en cuenta que también desactivé Always Allow Scanning , ya que dice:

Permita que el servicio de ubicación de Google y otras aplicaciones escanee redes Wi-Fi, incluso cuando el Wi-Fi esté apagado

Entonces, eso ciertamente sesgaría los resultados si estuviera habilitado.

Tenga en cuenta que también tuve el modo de ubicación configurado en el modo de ahorro de batería para todas las pruebas, por lo que la radio del GPS estuvo apagada todo el tiempo.

Estos son los resultados de PRIORITY_BALANCED_POWER_ACCURACY , ACCESS_COARSE_LOCATION y no WiFi:

 accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021 

Entonces, dice una precisión de 2000 metros, y aquí está qué tan lejos están las coordenadas reales, la flecha verde muestra dónde estoy realmente:

enter image description here

Luego, habilité WiFi, y realicé nuevamente la prueba, y sorprendentemente, ¡los resultados fueron exactamente los mismos!

 accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021 

Luego, cambié a LocationRequest.PRIORITY_LOW_POWER en LocationRequest mientras mantengo android.permission.ACCESS_COARSE_LOCATION en AndroidManifest.xml.

No wifi:

 accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021 

Con WiFi:

 accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021 

¡Los resultados fueron exactamente los mismos otra vez! El uso de PRIORITY_LOW_POWER tuvo los mismos resultados que con PRIORITY_BALANCED_POWER_ACCURACY , ya que el estado de WiFi no pareció tener ningún efecto en la precisión de las coordenadas.

Luego, solo para cubrir todas las bases, cambié de nuevo a LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY , y cambié el AndroidManifest.xml a ACCESS_FINE_LOCATION :

  

Primera prueba, sin WiFi:

 accuracy: 826.0 lat: 37.7825458 lon: -122.3948752 

Entonces, dice una precisión de 826 metros, y aquí está lo cerca que estaba en el mapa:

enter image description here

Luego, encendí el WiFi, y aquí está el resultado:

 accuracy: 18.847 lat: 37.779679 lon: -122.3930918 

Literalmente, como puedes ver en el mapa:

enter image description here

Parece que importa menos lo que usa en su LocationRequest en el código Java, y más qué permiso usa en AndroidManifest.xml, ya que los resultados aquí muestran claramente que al usar ACCESS_FINE_LOCATION , tener la radio WiFi encendida o apagada hizo que diferencia en la precisión, y también fue más precisa en general.

Ciertamente parece como si la documentación fuera un poco falsa, y que al usar android.permission.ACCESS_COARSE_LOCATION , tener la radio WiFi encendida o apagada no hace la diferencia cuando tu aplicación es la única que hace solicitudes de ubicación.

Otra cosa que indica la documentación es que el uso de PRIORITY_BALANCED_POWER_ACCURACY permitirá que su aplicación “se conecte” a las solicitudes de ubicación realizadas por otras aplicaciones. De la documentación:

Solo se les asignará la culpa de poder por el intervalo establecido por setInterval (largo), pero aún pueden recibir ubicaciones activadas por otras aplicaciones a una velocidad de hasta setFastestInterval (long).

Entonces, si el usuario abre Google Maps, de acuerdo con la documentación, su aplicación puede obtener una ubicación más precisa en ese punto. Esa es una de las principales ventajas del uso del nuevo Proveedor de ubicación fusionada en lugar de las API anteriores, ya que disminuye la cantidad de consumo de batería de su aplicación sin mucho trabajo de su parte.

Editar: realicé una prueba de esta funcionalidad para ver qué sucedería al usar ACCESS_COARSE_LOCATION .

Primera prueba: ACCESS_COARSE_LOCATION , PRIORITY_BALANCED_POWER_ACCURACY y WiFi en:

 accuracy: 2000.0 lat: 37.78378378378378 lon: -122.38041129850662 

Eso me colocó en el agua, bastante lejos de mi ubicación actual. Luego, salí de la aplicación de prueba, inicié Google Maps, que me ubicó exactamente donde estoy, y luego relancé la aplicación de prueba. ¡La aplicación de prueba no pudo volver a la ubicación de Google Maps, y el resultado fue exactamente el mismo que antes!

 accuracy: 2000.0 lat: 37.78378378378378 lon: -122.38041129850662 

Volví a probar esto algunas veces, solo para estar seguro, pero realmente parece que el uso de ACCESS_COARSE_LOCATION también desactiva la capacidad de las aplicaciones para “conectarse” en ubicaciones obtenidas por otras aplicaciones.

Parece que usar ACCESS_COARSE_LOCATION en AndroidManifest.xml realmente paraliza la aplicación en términos de obtener datos de ubicación precisos.

En conclusión, lo único que puede hacer es concentrarse en la mejor combinación de configuraciones que funcione para usted y su aplicación, y con suerte los resultados de esta prueba pueden ayudarlo a tomar esa decisión.

Cuando solicite el permiso ACCESS_COARSE_LOCATION, el cliente de ubicación fusionada le dará una precisión de bloque de ciudad, ese es el comportamiento previsto y está escrito en la documentación. Echa un vistazo aquí en “Especificar permisos de la aplicación”
Lo que puedo sugerir es que uses el proveedor de ubicación de Android normal (no la ubicación fusionada) e intentes acceder al proveedor de RED. Debería darte la precisión WIFI.