Мне нужно написать приложение, которое каждые 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)
решить эту проблему.
Тип сигнализации должен быть одной из констант _WAKEUP, например RTC_WAKEUP – msh
@msh См. Обновление 2. –
Сначала попробуйте http://stackoverflow.com/questions/4459058/alarm-manager-example - если это работает, используйте Это. Обратите внимание, что он поддерживает только wakelock до тех пор, пока onReceive не вернется, если вам нужно работать дольше - приобретете свой собственный – msh