web-dev-qa-db-fra.com

La permission ACCESS_COARSE_LOCATION donne une précision de tour de cellule sur Android

Je fais des tests avec la fonction requestLocationUpdates() à partir de FusedLocationApi. J'utilise le PRIORITY_BALANCED_POWER_ACCURACY . Une précision de bloc de ville me convient.

Lorsque je demande l'autorisation ACCESS_FINE_LOCATION , j'obtiens une précision de 100 m, ce qui est excellent avec GPS désactivé. Comme je n'ai pas besoin d'une précision GPS mais d'une précision de bloc de ville, je voudrais demander uniquement le ACCESS_COARSE_LOCATION autorisation. Cependant, lorsque je demande le ACCESS_COARSE_LOCATION permission, j'obtiens une précision de 2 km. Il semble que le périphérique n'utilise plus l'autorisation Wifi et seulement une précision de tour de cellule.

Comment puis-je avoir une meilleure précision avec l'autorisation ACCESS_COARSE_LOCATION ?

Remarque: le GPS est désactivé sur mon appareil de test.

21
poiuytrez

C'est un problème intéressant et j'avais l'impression que l'utilisation de ACCESS_COARSE_LOCATION utiliserait le WiFi, car c'est ce que dit la documentation.

La documentation de ACCESS_COARSE_LOCATION États:

Permet à une application d'accéder à l'emplacement approximatif dérivé de sources d'emplacement réseau telles que les tours de téléphonie cellulaire et le Wi-Fi.

Donc, je l'ai mis à l'épreuve, et les résultats sont surprenants.

Voici le code que j'ai utilisé pour tester avec:

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:

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

build.gradle:

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

Le premier test que j'ai fait a été avec PRIORITY_BALANCED_POWER_ACCURACY, et pas de WiFi. Notez que j'ai également désactivé Always Allow Scanning, puisqu'il indique:

Laissez Google Location Service et d'autres applications rechercher des réseaux Wi-Fi, même lorsque le Wi-Fi est désactivé

Donc, cela fausserait certainement les résultats s'il était activé.

Notez que j'avais également réglé le mode de localisation en mode d'économie de batterie pour tous les tests, de sorte que la radio GPS était éteinte tout le temps.

Voici les résultats de PRIORITY_BALANCED_POWER_ACCURACY, ACCESS_COARSE_LOCATION, et pas de WiFi:

accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021

Donc, il indique une précision de 2000 mètres, et voici à quelle distance sont les coordonnées réelles, la flèche verte montre où je suis réellement:

enter image description here

Ensuite, j'ai activé le WiFi, et j'ai relancé le test, et étonnamment, les résultats étaient exactement les mêmes!

accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021

Ensuite, je suis passé à LocationRequest.PRIORITY_LOW_POWER dans le LocationRequest tout en gardant Android.permission.ACCESS_COARSE_LOCATION dans AndroidManifest.xml.

Pas de wifi:

accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021

Avec WiFi:

accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021

Les résultats étaient exactement les mêmes à nouveau! En utilisant PRIORITY_LOW_POWER avait les mêmes résultats que l'utilisation de PRIORITY_BALANCED_POWER_ACCURACY, dans la mesure où l'état WiFi ne semble pas avoir d'effet sur la précision des coordonnées.

Ensuite, juste pour couvrir toutes les bases, je suis redevenu LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY et a basculé le fichier AndroidManifest.xml sur ACCESS_FINE_LOCATION:

<uses-permission Android:name="Android.permission.ACCESS_FINE_LOCATION" />

Premier test, pas de WiFi:

accuracy: 826.0 lat: 37.7825458 lon: -122.3948752

Ainsi, il indique une précision de 826 mètres, et voici à quel point il était proche sur la carte:

enter image description here

Ensuite, j'ai activé le WiFi, et voici le résultat:

accuracy: 18.847 lat: 37.779679 lon: -122.3930918

C'est littéralement sur place, comme vous pouvez le voir sur la carte:

enter image description here

Il semble que peu importe ce que vous utilisez dans votre LocationRequest dans le code Java, et plus quelle autorisation vous utilisez dans AndroidManifest.xml, car les résultats ici montrent clairement que lors de l'utilisation de ACCESS_FINE_LOCATION, avoir la radio WiFi allumée ou éteinte a fait une énorme différence dans la précision, et c'était aussi plus précis en général.

Il semble certainement que la documentation soit un peu erronée, et qu'en utilisant Android.permission.ACCESS_COARSE_LOCATION, l'activation ou la désactivation de la radio WiFi ne fait aucune différence lorsque votre application est la seule à effectuer des demandes de localisation.

La documentation indique également que l'utilisation de PRIORITY_BALANCED_POWER_ACCURACY permettra à votre application de se "superposer" aux demandes de localisation faites par d'autres applications. De la documentation:

On ne leur attribuera le blâme de puissance que pour l'intervalle défini par setInterval (long), mais peut toujours recevoir des emplacements déclenchés par d'autres applications à un taux allant jusqu'à setFastestInterval (long).

Donc, si l'utilisateur ouvre Google Maps, selon la documentation, votre application peut obtenir un emplacement plus précis à ce stade. C'est l'un des principaux avantages de l'utilisation du nouveau fournisseur de localisation fusionné plutôt que des anciennes API, car cela diminue la consommation de batterie de votre application sans trop de travail de votre part.

Edit: J'ai effectué un test de cette fonctionnalité, pour voir ce qui se passerait lors de l'utilisation de ACCESS_COARSE_LOCATION.

Premier test: ACCESS_COARSE_LOCATION, PRIORITY_BALANCED_POWER_ACCURACY, et WiFi activé:

accuracy: 2000.0 lat: 37.78378378378378 lon: -122.38041129850662

Cela m'a placé dans l'eau, assez loin de mon emplacement actuel. Ensuite, j'ai quitté l'application de test, lancé Google Maps, qui m'a localisé exactement où je suis, puis relancé l'application de test. L'application de test n'a pas pu se superposer à l'emplacement à partir de Google Maps, et le résultat était exactement le même qu'avant!

accuracy: 2000.0 lat: 37.78378378378378 lon: -122.38041129850662

J'ai re-testé cela plusieurs fois, juste pour être sûr, mais ça ressemble vraiment à utiliser ACCESS_COARSE_LOCATION désactive également la possibilité pour les applications de se superposer aux emplacements obtenus par d'autres applications.

Cela ressemble à utiliser ACCESS_COARSE_LOCATION dans AndroidManifest.xml paralyse vraiment l'application pour obtenir des données de localisation précises.

En conclusion, la seule chose que vous pouvez vraiment faire est de vous concentrer sur la meilleure combinaison de paramètres qui fonctionnent pour vous et votre application, et j'espère que les résultats de ce test pourront vous aider à prendre cette décision.

53
Daniel Nugent

Lorsque vous demandez l'autorisation ACCESS_COARSE_LOCATION, le client de localisation fusionné vous donnera une précision de bloc de ville, c'est le comportement prévu et c'est écrit dans la documentation. Jetez un œil ici sous "Spécifier les autorisations des applications"
Ce que je peux suggérer, c'est que vous utilisez le fournisseur d'emplacement régulier Android (emplacement non fusionné) et essayez d'accéder au fournisseur RÉSEAU. Cela devrait vous donner une précision WIFI.

3
Ohad Zadok