2010-06-25 39 views
9

Meine App überprüft zu einem bestimmten Zeitpunkt, ob sich ein Benutzer an einem bestimmten Standort befindet. Ich benutze den Alarmmanager einen Dienst zu starten, die diesen Aufruf macht:Android - Zuverlässiger Zugriff auf den aktuellen Standort

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

Und auch überprüft:

locationManager.getLastKnownLocation(bestProvider); 

Aber ich habe Probleme, wenn sie auf einem realen Gerät läuft. Zum einen ist getLastKnownLocation höchstwahrscheinlich der letzte Ort, an dem das GPS an war, der irgendwo sein könnte (d. H. Es könnte Meilen von dem aktuellen Standort des Benutzers entfernt sein). Also warte ich einfach auf requestLocationUpdates Rückrufe, und wenn sie nicht innerhalb von zwei Minuten da sind, entfernen Sie den Hörer und geben Sie auf, oder?

Falsch, weil, wenn der Standort des Benutzers bereits stabil ist (d. H. Er hat kürzlich GPS verwendet und sich nicht bewegt hat), wird mein Listener nie aufgerufen, da sich die Position nicht ändert. Aber das GPS wird laufen, bis mein Hörer entfernt wird, die Batterie entleerend ...

Was ist der rechte Weg, um den gegenwärtigen Standort zu erhalten, ohne einen alten Standort für den gegenwärtigen Standort zu verwechseln? Es macht mir nichts aus, ein paar Minuten zu warten.

EDIT: Es ist möglich, dass ich falsch liege, wenn der Hörer nicht angerufen wird, es kann nur ein wenig länger dauern, als ich dachte ... Schwer zu sagen. Ich würde eine endgültige Antwort noch schätzen.

Antwort

5

Der Code kann so etwas sein:

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 
     } 
    } 
} 

Wir die Hörer starten und einige Zeit für die Aktualisierung warten (20 Sekunden in meinem Beispiel). Wenn wir während dieser Zeit ein Update erhalten, verwenden wir es. Wenn wir während dieser Zeit keine Aktualisierung erhalten, verwenden wir den Wert getLastKnownLocation und stoppen den Listener.

Sie können meinen kompletten Code hier What is the simplest and most robust way to get the user's current location on Android?

EDIT (durch Fragesteller) sehen: Das meiste der Antwort ist, aber meine endgültige Lösung verwendet ein Handler anstelle einem Timer.

+0

Können Sie einen Beispielcode bereitstellen? Wie würden Sie beispielsweise 2 Minuten oder so warten, wenn der Standort-Listener nicht aufgerufen wird? – noah

+0

Code-Snippet hinzugefügt – Fedor

4

Wenn der Standort des Benutzers bereits stabil ist, gibt getLastKnownLocation den aktuellen Standort zurück. Ich würde zuerst getLastKnownLocation anrufen, den Zeitstempel ansehen (vergleiche Location.getElapsedRealTimeNanos() mit SystemClock.elapsedRealTimeNanos()) und dann einen Listener registrieren, wenn der Fix zu alt ist.

+0

Danke, ich wusste nicht über getTime(). Das Problem dabei ist, wie alt muss eine Zeit sein, bevor der Standortanbieter es als zu alt ansieht? Wie kann ich garantieren, dass mein Hörer angerufen wird, wenn ich diesen Ort nicht verwende? – noah

+1

Der Standortanbieter hält es nicht für zu alt, es wird nie verworfen (soweit ich weiß). Sie müssen entscheiden, wann Sie das Update für zu alt halten und ggf. Updates anfordern. Dann können Sie den alten Speicherort immer noch verwenden, wenn innerhalb einer bestimmten Zeit keine Aktualisierung erfolgt. – cristis

+2

Hier ist ein kleines Problem: Die API definiert nicht den Ursprung des von Location.getTime() zurückgegebenen Zeitstempels. Für GPS scheint es Satellitenzeit zu sein. Für den Netzwerkanbieter scheint es die lokale Gerätezeit zu sein. Das macht es etwas schwierig, das Alter eines Standorts zuverlässig zu bestimmen - es wird die Möglichkeit in Betracht gezogen, dass die Uhr eines Benutzers ungenau oder die Zeitzone möglicherweise falsch konfiguriert ist. – sstn

Verwandte Themen