В настоящее время я работаю над приложением, которое должно проверять местоположение пользователя каждые пять минут и отправлять координаты на сервер. Я решил использовать API FusedLocation в Сервисах Google Play вместо старого простого API LocationManager, главным образом потому, что я заметил уровень приоритета LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY, который утверждает, что обеспечивает 100-метровый уровень точности при разумных использование батареи, что ИМЕННО то, что мне нужно.
В моем случае у меня есть Activity, структура наследования которого:
public class MainActivity extends AppCompatActivity implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener
и который реализует соответствующие обратные вызовы (onConnected, onConnectionFailed, onConnectionSuspended, onLocationChanged). Я также получаю экземпляр GoogleApiClient с помощью этого метода, как это предлагается в официальной документации:
protected synchronized GoogleApiClient buildGoogleApiClient() {
return new GoogleApiClient.Builder(this).addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
В onConnected я запускаю обновления местоположения, используя
LocationServices.FusedLocationApi.requestLocationUpdates(mApiClient,
mLocationRequest, this);
... и фиксируйте изменения в onLocationChanged().
Однако я быстро обнаружил, что обновления местоположения, кажется, прекращаются через некоторое время. Возможно, это потому, что этот метод привязан к жизненному циклу Activity, я не уверен. Во всяком случае, я попытался обойти это, создав внутренний класс, который расширяет IntentService и запустил его с помощью AlarmManager. Итак, в onConnected я сделал это:
AlarmManager alarmMan = (AlarmManager) this
.getSystemService(Context.ALARM_SERVICE);
Intent updateIntent = new Intent(this, LocUpService.class);
PendingIntent pIntent = PendingIntent.getService(this, 0, updateIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
alarmMan.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, 0,
1000 * 60 * 5, pIntent);
Класс LocUpService выглядит так:
public static class LocUpService extends IntentService {
public LocUpService() {
super("LocUpService");
}
@Override
protected void onHandleIntent(Intent intent) {
Coords coords = LocationUpdater.getLastKnownLocation(mApiClient);
}
}
LocationUpdater — это еще один класс, который содержит статический метод getLastKnownLocation, а именно:
public static Coords getLastKnownLocation(GoogleApiClient apiClient) {
Coords coords = new Coords();
Location location = LocationServices.FusedLocationApi
.getLastLocation(apiClient);
if (location != null) {
coords.setLatitude(location.getLatitude());
coords.setLongitude(location.getLongitude());
Log.e("lat ", location.getLatitude() + " degrees");
Log.e("lon ", location.getLongitude() + " degrees");
}
return coords;
}
Но сюрприз!! Я получаю «IllegalArgumentException: требуется параметр GoogleApiClient», когда я четко передаю ссылку на статический метод, который снова, я думаю, должен иметь какое-то отношение к экземпляру GoogleApiClient, связанному с жизненным циклом Activity, и что-то идет не так с передачей экземпляра в Служба намерений.
Вот я и думаю: как мне получать регулярные обновления местоположения каждые пять минут и при этом не сойти с ума? Должен ли я расширять службу, реализовывать все обратные вызовы интерфейса в этом компоненте, создавать там экземпляр GoogleApiClient и поддерживать его работу в фоновом режиме? Нужно ли мне, чтобы AlarmManager запускал службу, которая расширяет IntentService каждые пять минут для выполнения работы, снова имея все соответствующие обратные вызовы и GoogleApiClient, созданные в IntentService? Продолжать ли мне делать то, что я делаю сейчас, но создавать GoogleApiClient как синглтон, ожидая, что это будет иметь значение? Как бы вы это сделали?
Спасибо и извините, что так многословно.