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.