Как отслеживать местоположение мобильного телефона Android?

Мне нужно написать приложение, которое каждые 5 минут определяет текущее местоположение мобильного телефона (используя всех свободных, доступных поставщиков местоположения) и отправляет его на сервер.

Если какой-либо провайдер местоположения не работает в начале приложения, но становится доступным позже, приложение также должно обработать свои данные о местоположении.

Для этого я реализовал следующий класс. В одном из моих действий я создаю его экземпляр и вызываю его метод startTrackingUpdates . locationChangeHandler выполняет обработку данных местоположения.

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

Я создал приложение и установил его на свой мобильный телефон. Затем, утром, я взял свой телефон, пошел на работу, потом вернулся домой. Дома я проверил результаты однодневной работы приложения и нашел только одну запись в базе данных.

При условии, что остальная часть системы (передача данных местоположения на сервер, сохранение в базе данных) работает правильно, у меня должна быть некоторая проблема в коде отслеживания местоположения ( onLocationChanged не был вызван, хотя я несколько раз менял свое местоположение).

Что не так с моим кодом (как его изменить, для того, чтобы onLocationChanged вызывался всякий раз, когда местоположение телефона MIN_DISTANCE_CHANGE_FOR_UPDATES более чем на MIN_DISTANCE_CHANGE_FOR_UPDATES соответствии с одним из поставщиков locatin)?

Обновление 1 (18.08.2013 13:59 MSK):

Я изменил свой код в соответствии с рекомендациями msh . Я запускаю таймер, используя следующий код:

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

В этой activity я помещаю следующий обработчик событий таймера:

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

Когда телефон включен, все работает так, как ожидалось – onActivityResult выполняется один раз в INTERVAL миллисекундах.

Но когда я onActivityResult кнопку питания (экран становится отключенным), onActivityResult не вызывается вообще. Когда я снова onActivityResult кнопку питания, onActivityResult выполняется столько раз, сколько INTERVAL прошло с того момента, как я выключил телефон. Если я выключу телефон за 1 * INTERVAL миллисекунды, он будет срабатывать один раз. Если бы я выключил телефон за 2 * INTERVAL миллисекунды, он будет стрелять дважды и т. Д.

Примечание: «Отключение» означает короткое нажатие кнопки питания (телефон все еще «живет» и, например, реагирует на входящие SMS).

Как мне изменить код startSavingGeoData чтобы метод onActivityResult выполнялся каждые миллисекунды INTERVAL , даже когда телефон спит?

Обновление 2 (18.08.2013 19:29 MSK): ни alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 0, INTERVAL, pendingIntent) , ни alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, INTERVAL, INTERVAL, pendingIntent) решили проблему.

Вероятно, ваш код правильный, но поставщики местоположения не работают, когда ваш телефон спит. Вам может потребоваться приобрести wakelock (если вы не заботитесь об энергопотреблении) или использовать AlarmManager и планировать свое приложение для пробуждения и проверки местоположения периодически (вам все равно необходимо иметь активный wakelock, пока вы ожидаете обновления, либо Приобретенный AlamManager, или ваш собственный).