Jak stale śledzić lokalizację telefonu komórkowego z Androidem?

Muszę napisać aplikację, która co 5 minut określa aktualną lokalizację telefonu komórkowego (używając wszystkich darmowych, dostępnych dostawców lokalizacji) i wysyła go na serwer.

Jeśli jakiś dostawca lokalizacji nie działa na początku aplikacji, ale staje się dostępny później, aplikacja powinna również przetworzyć dane lokalizacji.

W tym celu zaimplementowałem następującą klasę. W jednym z moich działań tworzę jego instancję i dzwonię do niegostartTrackingUpdates metoda.locationChangeHandler przetwarza dane lokalizacji.

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

Zbudowałem aplikację i zainstalowałem ją na moim telefonie komórkowym. Potem rano wziąłem telefon, poszedłem do pracy i wróciłem do domu. W domu sprawdziłem wyniki całodziennej pracy aplikacji i znalazłem tylko jeden rekord w bazie danych.

Pod warunkiem, że reszta systemu (transmisja danych lokalizacji na serwer, zapisywanie w bazie danych) działa poprawnie, muszę mieć jakiś problem w kodzie śledzenia lokalizacji (onLocationChanged nie został wywołany, mimo że kilka razy zmieniłem lokalizację).

Co jest nie tak z moim kodem (jak powinienem go zmienić, abyonLocationChanged do wywołania, gdy lokalizacja telefonu zmieni się o więcej niżMIN_DISTANCE_CHANGE_FOR_UPDATES liczniki według jednego z dostawców lokalizacji)?

Aktualizacja 1 (18.08.2013 13:59 MSK):

Zmieniłem kod wedługmsh zalecenia. Uruchamiam timer za pomocą następującego kodu:

public void startSavingGeoData() {
    final IAlarmManager alarmManager = activity.getAlarmManager();
    final IPendingIntent pendingIntent = activity.createPendingResult(
            ALARM_ID, intentFactory.createEmptyIntent(), 0);
    alarmManager.setRepeating(INTERVAL, pendingIntent);
}

wactivity Umieściłem następujący program obsługi zdarzeń timera:

@Override
protected void onActivityResult(final int aRequestCode, final int aResultCode, 
        final Intent aData) {
    geoDataSender.processOnActivityResult(aRequestCode, aResultCode, 
            new IntentWrapper(aData));
}

Gdy telefon jest włączony, wszystko działa zgodnie z oczekiwaniami -onActivityResult jest wykonywane raz wINTERVAL milisekundy.

Ale kiedy naciskam przycisk zasilania (ekran zostaje wyłączony),onActivityResult nie jest w ogóle wywoływany. Po ponownym naciśnięciu przycisku zasilaniaonActivityResult jest wykonywany tyle razy, coINTERVAL minęło od czasu, kiedy wyłączyłem telefon. Jeśli wyłączę telefon1 * INTERVAL w milisekundach będzie strzelać raz. Jeśli wyłączę telefon2 * INTERVAL w milisekundach będzie strzelać dwa razy itd.

Uwaga: „Wyłączając” mam na myśli krótkie naciśnięcie przycisku zasilania (telefon nadal „żyje” i reaguje na przykład na przychodzące wiadomości SMS).

Jak zmodyfikować kodstartSavingGeoData w celu zastosowania metodyonActivityResult do wykonania coINTERVAL milisekundy, nawet gdy telefon śpi?

Aktualizacja 2 (18.08.2013 19:29 MSK): AnialarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 0, INTERVAL, pendingIntent), anialarmManager.setRepeating(AlarmManager.RTC_WAKEUP, INTERVAL, INTERVAL, pendingIntent) Rozwiązać problem.

questionAnswers(1)

yourAnswerToTheQuestion