2010-06-25 6 views
9

Mon application vérifie à un moment donné si un utilisateur se trouve à un emplacement donné. J'utilise le gestionnaire d'alarme pour lancer un service qui fait cet appel:Android - Obtenir de manière fiable l'emplacement actuel

locationManager.requestLocationUpdates(bestProvider, 0, 0, listener); 

Et vérifie également:

locationManager.getLastKnownLocation(bestProvider); 

Mais je vais avoir des problèmes lors de l'exécution sur un périphérique réel. Pour une chose, getLastKnownLocation est probablement le dernier endroit où le GPS était, ce qui pourrait être n'importe où (c'est-à-dire, il pourrait être miles de l'emplacement actuel de l'utilisateur). Donc, je vais attendre requestLocationUpdates rappels, et si elles ne sont pas là dans les deux minutes, retirez l'auditeur et abandonner, non? Incorrect, car si l'emplacement de l'utilisateur est déjà stable (c'est-à-dire qu'il a utilisé le GPS récemment et qu'il n'a pas bougé), alors mon écouteur ne sera jamais appelé car l'emplacement ne change pas. Mais le GPS fonctionnera jusqu'à ce que mon auditeur soit retiré, vidant la batterie ...

Quelle est la bonne façon d'obtenir l'emplacement actuel sans confondre un ancien emplacement pour l'emplacement actuel? Cela ne me dérange pas d'attendre quelques minutes.

EDIT: Il est possible que je me trompe sur le fait que l'auditeur ne soit pas appelé, cela peut prendre un peu plus de temps que je ne le pensais ... Difficile à dire. J'apprécierais une réponse définitive encore.

Répondre

5

Le code peut être quelque chose comme ça:

public class MyLocation { 
    Timer timer1; 
    LocationManager lm; 

    public boolean getLocation(Context context) 
    { 
     lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); 
     lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps); 
     timer1=new Timer(); 
     timer1.schedule(new GetLastLocation(), 20000); 
     return true; 
    } 

    LocationListener locationListenerGps = new LocationListener() { 
     public void onLocationChanged(Location location) { 
      timer1.cancel(); 
      lm.removeUpdates(this); 
      //use location as it is the latest value 
     } 
     public void onProviderDisabled(String provider) {} 
     public void onProviderEnabled(String provider) {} 
     public void onStatusChanged(String provider, int status, Bundle extras) {} 
    }; 

    class GetLastLocation extends TimerTask { 
     @Override 
     public void run() { 
      lm.removeUpdates(locationListenerGps); 
      Location location=lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); 
      //use location as we have not received the new value from listener 
     } 
    } 
} 

Nous commençons l'auditeur et d'attendre la mise à jour pendant un certain temps (20 secondes dans mon exemple). Si nous recevons une mise à jour pendant cette période, nous l'utilisons. Si nous ne recevons pas de mise à jour pendant cette période, nous utilisons la valeur getLastKnownLocation et arrêtons l'écouteur.

Vous pouvez voir mon code complet ici What is the simplest and most robust way to get the user's current location on Android?

EDIT (adoptée par le demandeur): Ceci est la majeure partie de la réponse, mais ma solution finale utilise un Handler au lieu d'une minuterie.

+0

Pouvez-vous fournir un exemple de code? Par exemple, comment voulez-vous attendre 2 minutes ou quelque chose comme ça si l'écouteur de localisation n'est pas appelé? – noah

+0

Extrait de code ajouté – Fedor

4

Si l'emplacement de l'utilisateur est déjà stable, getLastKnownLocation renverra l'emplacement actuel. J'appelle d'abord getLastKnownLocation, regardez l'horodatage (comparez Location.getElapsedRealTimeNanos() avec SystemClock.elapsedRealTimeNanos()) puis enregistrez un écouteur si le correctif est trop ancien.

+0

Merci, je ne connaissais pas getTime(). Le problème avec ceci est, quel âge doit avoir un temps avant que le fournisseur d'emplacement ne le considère trop vieux? Comment puis-je garantir que mon interlocuteur sera appelé si je n'utilise pas cet emplacement? – noah

+1

Le fournisseur d'emplacement ne considère pas qu'il est trop vieux, il ne le rejette jamais (pour autant que je sache). Vous devez décider quand vous jugez que le correctif est trop ancien et demander des mises à jour si nécessaire. Ensuite, vous pouvez toujours utiliser l'ancien emplacement s'il n'y a pas de mise à jour dans un délai donné. – cristis

+2

Il y a un petit problème ici: l'API ne définit pas l'origine de l'horodatage retourné par Location.getTime(). Pour le GPS, il semble que ce soit l'heure satellite. Pour le fournisseur de réseau, il semble que ce soit l'heure du périphérique local. Cela rend quelque peu difficile de déterminer de manière fiable l'âge d'un emplacement - considéré comme la possibilité que l'horloge d'un utilisateur soit inexacte ou que le fuseau horaire soit mal configuré. – sstn

Questions connexes