Создание надежного и стабильного сервиса определения местоположения с расписанием
Функция, которую я хотел бы достичь:
В определенный день должен запуститься сервис, который получает информацию о местоположении и отправляет ее на сервер. На определенную дату сервис должен остановиться.
- Время начала и окончания очень важно, чтобы быть точным.
- Сервис должен быть максимально надежным, ОС не должна его убивать.
- Запуск и окончание службы должны быть автоматическими, без участия пользователя.
Вот чего я достиг:
- В моем приложении есть база данных, в которой хранятся "расписания". Время начала, время окончания.
- У меня есть класс ServiceScheduler, который считывает расписания из БД и устанавливает сигналы тревоги с AlarmManager на определенные даты, используя PendingIntents и WakefulBroadcastReceiver.
- WakefulBroadcastReceiver фактически запускает службу, и я получил еще один BroadcastReceiver для его остановки.
- Мой сервис - это простой сервис, поэтому НЕ является IntentService, я использую его в режиме startForeground.
Что я узнал в процессе, пытаясь сделать функцию надежной и удобной в использовании:
- Мой ServiceScheduler должен переустанавливать аварийные сигналы после перезагрузки устройства, потому что аварийные сигналы очищаются при выключении.
- Запуск режима переднего плана - отличный способ минимизировать вероятность того, что ОС убьет службу.
- Запуск службы с помощью WakefullBroadcastReceiver вместо простого BroadcastReceiver необходим для того, чтобы устройство выходило из спящего режима.
тесты:
- Служба еще не на 100% надежна, и я подозреваю, что в основе проблемы лежит спящий режим.
Мои вопросы:
Помогает ли спящий режим устройства нормально функционировать? - Значение получения информации о местоположении с "объединенным местоположением", кэширования местоположений в БД и передачи некоторых данных на сервер.
Возможно ли, что после запуска службы устройство может вернуться в спящий режим?
Если я решу держать устройство в активном состоянии в течение всего интервала во время работы службы, будет ли хорошей практикой приобретать блокировку активации в onCreate службы и отпускать ее в onDestroy?
Мой упрощенный код:
public class ServiceScheduler
{
//Class for scheduling a service from a scheduling instance (read from DB)
//.. much simple version just to explain
private void schedule(Scheduling scheduling){
//Intent for the ServiceStartBroadcastReceiver
Intent startServiceIntent = new Intent(ctx.getApplicationContext(), ServiceStartBroadcastReceiver.class);
//pending intent for the alarmManager
PendingIntent startPendingIntent = PendingIntent.getBroadcast(ctx.getApplicationContext(), 0, startServiceIntent, 0);
//setting alarm to start the service at the specific time
//setExact's required API level is too high for the project
alarmManager.set(AlarmManager.RTC_WAKEUP, scheduling.startTime.getTime(), startPendingIntent);
//Intent for the ServiceStopBroadcastReceiver
Intent endServiceIntent = new Intent(ctx.getApplicationContext(), ServiceStopBroadcastReceiver.class);
//pending intent for the alarmManager
PendingIntent endPendingIntent = PendingIntent.getBroadcast(ctx.getApplicationContext(), 0, endServiceIntent, 0);
//setting alarm to stop the service at the specific time
//setExact's required API level is too high for the project
alarmManager.set(AlarmManager.RTC_WAKEUP, scheduling.endTime.getTime(),endPendingIntent);
}
}
public class ServiceStartBroadcastReceiver extends WakefulBroadcastReceiver {
//BroadcastReceiver to start the service
@Override
public void onReceive(Context context, Intent intent) {
Intent startServiceIntent = new Intent(context, GpsService.class);
//start in wakeful mode
startWakefulService(context, startServiceIntent);
}
}
public class ServiceStopBroadcastReceiver extends BroadcastReceiver {
//BroadcastReceiver to stop the service
@Override
public void onReceive(Context context, Intent intent) {
//Stopping the service
Intent stopServiceIntent = new Intent(context, GpsService.class);
context.stopService(stopServiceIntent);
}
}
public class GpsService extends Service {
//Using wake lock, is it necessary?
private PowerManager.WakeLock wakeLock;
@Override
public void onCreate() {
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "locationServiceWakeLock");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//Wake lock !? is it necessary?
if (!wakeLock.isHeld()) {
wakeLock.acquire();
}
//completing the wakefull intent which is started at ServiceStartBroadcastReceiver
ServiceStartBroadcastReceiver.completeWakefulIntent(intent);
//Which mode should i use and why as return?
return START_REDELIVER_INTENT;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
//Wake lock !? is it necessary?
wakeLock.release();
}
}
Пожалуйста, расскажите мне все ваши советы
Я делаю это сейчас уже давно, и решение близко. Я прочитал все статьи и документацию, которые я нашел, но я все еще не уверен в некоторых вещах.