2013-08-15 3 views
9

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

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

Для этого я реализовал следующий класс. В одном из моих действий я создаю его экземпляр и вызываю его метод 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 метров в соответствии с одним из поставщиков локализаторов)?

Update 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 выполняется столько раз, сколько 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) решить эту проблему.

+0

Тип сигнализации должен быть одной из констант _WAKEUP, например RTC_WAKEUP – msh

+0

@msh См. Обновление 2. –

+0

Сначала попробуйте http://stackoverflow.com/questions/4459058/alarm-manager-example - если это работает, используйте Это. Обратите внимание, что он поддерживает только wakelock до тех пор, пока onReceive не вернется, если вам нужно работать дольше - приобретете свой собственный – msh

ответ

8

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

+0

. Я изменил код (см. «Обновление 1»), но он по-прежнему не работает должным образом. Есть идеи? –

+0

Вы можете создать свой код аварийного сигнала в этом примере http://stackoverflow.com/questions/4459058/alarm-manager-example – msh

+0

Да, этот пример работает, по крайней мере, метод для получения местоположения выполняется даже, когда телефон спит. –