Wie kann ich den Standort eines Android-Handys kontinuierlich verfolgen?
Ich muss eine App schreiben, die alle 5 Minuten den aktuellen Standort des Mobiltelefons ermittelt (unter Verwendung aller kostenlosen, verfügbaren Standortanbieter) und an einen Server sendet.
Wenn ein Standortanbieter beim Start der Anwendung nicht funktioniert, aber später verfügbar wird, sollte die Anwendung auch ihre Standortdaten verarbeiten.
Dazu habe ich folgende Klasse implementiert. In einer meiner Aktivitäten erstelle ich eine Instanz davon und rufe sie aufstartTrackingUpdates
Methode.locationChangeHandler
erledigt die Verarbeitung von Standortdaten.
public class LocationTracker implements ILocationTracker, LocationListener {
public static final long MIN_TIME_BETWEEN_UPDATES = 1000 * 60 * 5; // 5 minutes
public static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters
private ILocationManager locationManager;
private ILocationChangeHandler locationChangeHandler;
public LocationTracker(final ILocationManager aLocationManager,
final ILocationChangeHandler aLocationChangeHandler) {
this.locationManager = aLocationManager;
this.locationChangeHandler = aLocationChangeHandler;
}
public void startTrackingUpdates() {
final List<String> providers = locationManager.getAllProviders();
for (final String curProviderName : providers)
{
final ILocationProvider provider = locationManager.getLocationProvider(curProviderName);
if (!provider.hasMonetaryCost())
{
subscribeToLocationChanges(provider);
}
}
}
private void subscribeToLocationChanges(final ILocationProvider aProvider) {
locationManager.requestLocationUpdates(aProvider.getName(), MIN_TIME_BETWEEN_UPDATES,
(float)MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
}
public void onLocationChanged(final Location aLocation) {
locationChangeHandler.processLocationChange(new LocationWrapper(aLocation));
}
public void onProviderDisabled(final String aProvider) {
}
public void onProviderEnabled(final String aProvider) {
}
public void onStatusChanged(final String aProvider, final int aStatus,
final Bundle aExtras) {
}
}
Ich habe die Anwendung erstellt und auf meinem Mobiltelefon installiert. Dann, am Morgen, nahm ich mein Handy, ging zur Arbeit und ging dann zurück nach Hause. Zu Hause überprüfte ich die Ergebnisse einer Tagesarbeit der Anwendung und fand nur einen Datensatz in der Datenbank.
Unter der Voraussetzung, dass der Rest des Systems (Übertragung der Standortdaten an den Server, Speichern in der Datenbank) ordnungsgemäß funktioniert, muss der Standortverfolgungscode ein Problem aufweisen (onLocationChanged
wurde nicht aufgerufen, obwohl ich meinen Standort mehrmals geändert habe).
Was ist los mit meinem Code (wie soll ich ihn ändern, damit dieonLocationChanged
angerufen werden, wenn sich der Standort des Telefons um mehr alsMIN_DISTANCE_CHANGE_FOR_UPDATES
Meter nach einem der locatin Anbieter)?
Update 1 (18.08.2013 13:59 MSK):
Ich habe meinen Code entsprechend geändertmsh Empfehlungen. Ich starte den Timer mit folgendem Code:
public void startSavingGeoData() {
final IAlarmManager alarmManager = activity.getAlarmManager();
final IPendingIntent pendingIntent = activity.createPendingResult(
ALARM_ID, intentFactory.createEmptyIntent(), 0);
alarmManager.setRepeating(INTERVAL, pendingIntent);
}
In demactivity
Ich habe folgenden Timer-Event-Handler gesetzt:
@Override
protected void onActivityResult(final int aRequestCode, final int aResultCode,
final Intent aData) {
geoDataSender.processOnActivityResult(aRequestCode, aResultCode,
new IntentWrapper(aData));
}
Wenn das Telefon eingeschaltet ist, funktioniert alles wie erwartet -onActivityResult
wird einmal in ausgeführtINTERVAL
Millisekunden.
Aber wenn ich den Netzschalter drücke (Bildschirm wird deaktiviert),onActivityResult
wird überhaupt nicht aufgerufen. Wenn ich den Netzschalter erneut drücke,onActivityResult
wird so oft ausgeführt, wieINTERVAL
ist vergangen, seit ich das Telefon ausgeschaltet habe. Wenn ich das Telefon für ausgeschaltet habe1 * INTERVAL
Millisekunden, es wird einmal ausgelöst. Wenn ich das Telefon für ausgeschaltet habe2 * INTERVAL
Millisekunden, es wird zweimal ausgelöst usw.
Hinweis: Mit "Ausschalten" meine ich ein kurzes Drücken des Netzschalters (das Telefon "lebt" weiterhin und reagiert beispielsweise auf eingehende SMS).
Wie soll ich den Code von ändern?startSavingGeoData
in Ordnung für die MethodeonActivityResult
ausgeführt werdenINTERVAL
Millisekunden, auch wenn das Telefon schläft?
Update 2 (18.08.2013 19:29 MSK): WederalarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 0, INTERVAL, pendingIntent)
, NochalarmManager.setRepeating(AlarmManager.RTC_WAKEUP, INTERVAL, INTERVAL, pendingIntent)
Problem gelöst.