web-dev-qa-db-fra.com

Comportement inattendu du fournisseur d'emplacement fusionné

voici comment j'enregistre mon application pour recevoir des mises à jour de localisation:

mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(Consts.ONE_MINUTE * 10);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
mLocationRequest.setFastestInterval(Consts.ONE_MINUTE);

Builder builder = new GoogleApiClient.Builder(context);
builder.addApi(ActivityRecognition.API);

mGoogleApiClient = builder.addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();

mGoogleApiClient.connect();

....
....

@Override
public void onConnected(Bundle connectionHint) {
   LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, locationUpdatespendingInent);
}

mon intention en attente a été invoquée en arrière-plan presque dans les intervalles exacts demandés ...

jusqu'ici tout va bien.

le problème: Lorsque le WIFI est désactivé/n'est connecté à aucun réseau, ou lorsqu'il n'y a pas de données réseau 3G/4G activées - le fournisseur de localisation fusionné ne fournit pas de nouvelles mises à jour de localisation !!

mes paramètres d'accès à la position sont activés et les satellites GPS et l'emplacement du réseau Wi-Fi et mobile sont vérifiés.

le problème encore plus gros: parfois dans ce cas, je reçois des rappels de mises à jour de localisation via l'intention en attente, mais avec le dernier emplacement qu'il connaissait (même si c'était il y a une heure, et je suis depuis longtemps disparu à des kilomètres de cet endroit)

selon la documentation de PRIORITY_BALANCED_POWER_ACCURACY:

Utilisé avec setPriority (int) pour demander une précision de niveau "bloc". La précision du niveau de bloc est considérée comme une précision d'environ 100 mètres. L'utilisation d'une précision grossière comme celle-ci consomme souvent moins d'énergie.

Je m'attends à ce que le fournisseur de localisation fusionné ouvre le GPS lorsqu'il n'a pas d'autre choix, ou du moins ne fournira pas de nouvelles mises à jour de localisation s'il n'en a pas.

n autre problème imprévisible et inquiétant:

J'ai changé PRIORITY_BALANCED_POWER_ACCURACY à PRIORITY_HIGH_ACCURACY afin de voir comment il se comporte (pendant 24 heures). tous les intervalles sont restés les mêmes (intervalle de 10 minutes entre les mises à jour). localisation précise en effet reçue même dans les téléphones sans réseau/carte SIM, mais - la batterie s'est épuisée rapidement! quand j'ai regardé l'historique de la batterie, j'ai été surpris de voir que la radio GPS était toujours en mode de transmission complète !!!! et j'ai également vu dans mon journal que la loction était reçue chaque minute, même que j'ai demandé l'emplacement toutes les dix minutes (je n'ai aucune autre application installée qui ouvre le GPS pour recevoir des emplacements ..)

J'ai remarqué ce comportement sur plusieurs appareils (tels que Moto X 2013, HTC One X, Nexus 5), tous avec les derniers services Google Play (version 6.1.11) et Android KitKat 4.4.4

mon application dépend beaucoup de l'emplacement actuel de l'utilisateur et reçoit périodiquement des mises à jour d'emplacement dans l'intervalle spécifié tant que l'utilisateur s'est connecté, donc je ne veux pas utiliser le PRIORITY_HIGH_ACCURACY mode, pour éviter la décharge de la batterie ..

mes questions:

  • est le fournisseur de localisation fusionné supposé utiliser le GPS s'il est configuré pour recevoir des mises à jour avec PRIORITY_BALANCED_POWER_ACCURACY et vous n'avez pas d'informations sur le WI-FI ou les tours de téléphonie cellulaire?

  • si c'est le cas, que fais-je de mal?

  • pourquoi je reçois des mises à jour de localisation trompeuses qui ne sont pas correctes? (comme je l'ai expliqué dans la section "encore plus gros problème" ..

  • pourquoi la radio GPS est ouverte tout le temps au lieu d'être ouverte pendant l'intervalle de 10 minutes lorsque j'ai utilisé le PRIORITY_HIGH_ACCURACY paramètre? (Je n'ai pas d'autres applications installées qui déclenchent des mises à jour de localisation plus rapidement ..)

26
Tal Kanel

Pour les questions spécifiées,

1. est le fournisseur de localisation fusionné supposé utiliser le GPS du tout s'il est configuré pour recevoir des mises à jour avec PRIORITY_BALANCED_POWER_ACCURACY Et n'avez pas d'informations WI-FI ou tours de téléphonie cellulaire? &
2. si c'est le cas, alors qu'est-ce que je fais mal?

Apparemment, aucune source explicitement unique n'est spécifiée dans la documentation. Avec les options PRIORITY, même via le code, la "source" de location obtenue est "fusionnée".
[location.getProvider() renvoie: "fusionné"]
J'ai vu le GPS utilisé uniquement lorsque LocationRequest a PRIORITY_HIGH_ACCURACY. Il n'utilise donc pas le GPS dans d'autres conditions.

4. pourquoi la radio GPS est ouverte tout le temps au lieu d'être ouverte pendant l'intervalle de 10 minutes lorsque j'ai utilisé le Paramètre PRIORITY_HIGH_ACCURACY? (Je n'ai pas d'autres applications installées qui déclenchent des mises à jour de localisation plus rapidement ..)

L'intervalle le plus rapide a été fixé à 1 minute. D'après ce que j'ai compris, le setFastestInterval est prioritaire sur setInterval lorsque la valeur de l'intervalle le plus rapide est plus courte que la valeur de setInterval.
Dans votre cas, 1 minute contre 10.
À propos de ne pas avoir d'autres applications installées qui déclenchent des mises à jour d'emplacement, son juste donné à titre d'exemple et non spécifié que seulement ce cas explicitement.

Cela contrôle le taux le plus rapide auquel votre application recevra les mises à jour d'emplacement, qui peut être plus rapide que setInterval (long) dans certaines situations (par exemple, si d'autres applications déclenchent des mises à jour d'emplacement).

Donc, ce qui se passe est avec PRIORITY_HIGH_ACCURACY, Il demande location sur l'intervalle le plus rapide réglé - 1min, en utilisant le GPS (sorte exclusivement).

3. pourquoi je reçois des mises à jour de localisation trompeuses qui ne sont pas correctes? (comme je l'ai expliqué dans la section "encore plus gros problème" ..

Vous devez également vérifier le code du mécanisme pendingIntent. Bien qu'il puisse y avoir quelques points à noter:
Vous pouvez ajouter un location.getTime() pour assurer et vérifier l'heure de l'emplacement obtenu. Très probablement, il n'est pas mis à jour, s'il n'y a pas de tours de cellules wifi à portée et que PRIORITY_BALANCED_POWER_ACCURACY Est utilisé.
Une précision au niveau du bloc de l'emplacement sur la première place, qui est utilisée lorsque "lastKnown" est appelé n'aiderait pas.

La consommation de la batterie était due à la combinaison du GPS et des mises à jour de 1 min. Essayez de définir l'intervalle le plus rapide sur 5 ou 10 minutes, si cela convient à votre implémentation, mais PRIORITY_BALANCED_POWER Peut ne pas vous aider si vous avez besoin d'un emplacement absolument précis. J'ajoute normalement une vérification de l'emplacement obtenu dans onLocationChanged et en fonction de cela, changez la priorité dans LocationRequest. Cela aide sûrement à obtenir un emplacement en général, sauf si je suis à l'intérieur d'un bâtiment sans ligne de visée car le GPS et le réseau Wifi sont désactivés.

19
Pararth

Je vous suggère d'utiliser AlarmManager et FusedLocationProvider ensemble de telle manière que votre AlarmManager déclenche une alarme toutes les 10 minutes en vue de démarrer les mises à jour de l'emplacement.

Une fois l'emplacement mis à jour, déconnectez le client d'emplacement. Vous n'avez pas besoin de le faire fonctionner tout le temps en définissant l'intervalle de temps dans LocationRequest. À la place, vous pouvez appeler le processus à chaque intervalle de temps en utilisant AlarmManager.

Dans ce type de mécanisme, vous bénéficierez des avantages suivants qui résoudront vos problèmes:

  • La radio GPS ne restera ouverte que pendant quelques secondes lors de la récupération de la position car vous allez vous déconnecter après avoir obtenu la première mise à jour de la position. Ainsi, la radio GPS ne restera pas ouverte tout le temps, la batterie sera donc économisée.
  • Vous pourrez obtenir un nouvel emplacement toutes les 10 minutes sans déconner avec l'ancien emplacement ou quelque chose.

J'espère que ce sera utile.

4
Mehul Joisar

Les tours cellulaires couvrent une zone de plusieurs kilomètres, elles ne sont donc pas les meilleures pour obtenir un emplacement. Regardez la précision de l'emplacement lorsque vous travaillez avec des emplacements.

@Override
public void onLocationChanged(Location location) {
    //it happens
    if (location == null) {
        return;
    }
    // all locations should have an accuracy
    if (!location.hasAccuracy()) {
        return;
    }
    // if its not accurate enough don't use it
    // this value is in meters
    if (location.getAccuracy() > 200) {
        return;
    }
}

Vous pouvez mettre un récepteur de diffusion sur l'état du réseau et lorsqu'il n'y a pas de connexion, vous pouvez redémarrer votre fournisseur de localisation avec priority_high_accuracy qui n'utilisera le GPS que lorsque l'utilisateur a activé le GPS, sinon il retombe sur le wifi et les tours de téléphonie cellulaire.

<action Android:name="Android.net.conn.CONNECTIVITY_CHANGE"/>

/** Checks whether the device currently has a network connection */

private boolean isDeviceOnline() {
    ConnectivityManager connMgr = (ConnectivityManager) activity
            .getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
    if (networkInfo != null && networkInfo.isConnected()) {
        return true;
    }
    return false;
}
3
danny117

Pour la mise à jour des coordonnées GPS, vous pouvez également utiliser les fournisseurs GPS et WI-FI. Pour la mise à jour de la position, utilisez également le paramètre de distance minimale. Je vais vous fournir un petit exemple de service GPS.

Réponses :

1) PRIORITY_BALANCED_POWER_ACCURACY pas utilisez le GPS.

2) Utilisez le GPS et le WI-FI pour détecter l'emplacement.

3) PRIORITY_BALANCED_POWER_ACCURACY probablement à cause de l'absence de WI-FI dans la zone.

Exemple de code:

public class GPSservice extends Service implements LocationListener {


    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 2;

    private static final long MIN_TIME_BW_UPDATES = 1000 * 1;

    double latitude, longitude;

    boolean isGPSEnabled = false;

    boolean isNetworkEnabled = false;

    boolean canGetLocation = false;

    Location location;

    protected LocationManager locationManager;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        getLocation();

        return super.onStartCommand(intent, flags, startId);
    }


    @Override
    public void onLocationChanged(Location location) {
        new LocationReceiver(location, getApplicationContext());
    }


    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {

    }

    @Override
    public void onProviderEnabled(String provider) {

    }

    @Override
    public void onProviderDisabled(String provider) {

    }

    public Location getLocation() {
        try {
            locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

            // getting GPS status
            isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

            isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

            if (!isGPSEnabled && !isNetworkEnabled) {
                Log.d("Network", "NO network");
            } else {
                this.canGetLocation = true;
                if (isNetworkEnabled) {
                    locationManager.requestLocationUpdates(
                            LocationManager.NETWORK_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                    Log.d("Network", "Network");
                    if (locationManager != null) {
                        location = locationManager
                                .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                        if (location != null) {
                            latitude = location.getLatitude();
                            longitude = location.getLongitude();
                        }
                    }
                }
                if (isGPSEnabled) {
                    if (location == null) {
                        locationManager.requestLocationUpdates(
                                LocationManager.GPS_PROVIDER,
                                MIN_TIME_BW_UPDATES,
                                MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                        Log.d("GPS Enabled", "GPS Enabled");
                        if (locationManager != null) {
                            location = locationManager
                                    .getLastKnownLocation(LocationManager.GPS_PROVIDER);
                            if (location != null) {
                                latitude = location.getLatitude();
                                longitude = location.getLongitude();
                            }
                        }
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return location;
    }
}
0
Oleg Gordiichuk