Поддерживайте работу даже в том случае, если телефон спит?

У меня есть Сервис в моем приложении, которое рассчитано на запуск каждые 10 минут. Он в основном проверяет наши серверы, чтобы убедиться, что все работает правильно и уведомляет пользователя о любых проблемах. Я создал это приложение для внутреннего использования в нашей компании.

Мой коллега использовал приложение в течение долгого уик-энда и заметил, что никаких проверок не было, когда устройство перешло спать. У меня создалось впечатление, что Служба должна была работать в фоновом режиме, пока я не позвоню в свой код stopService() .

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

Я слышал о чем-то, называемом WakeLock который предназначен для того, чтобы экран не WakeLock чего я не хочу. Затем я услышал о другой вещи, называемой частичным WakeLock , которая поддерживает работу процессора, даже когда устройство спит. Последний звучит ближе к тому, что мне нужно.

Как мне приобрести этот WakeLock, и когда я должен его отпустить, и есть ли другие способы обойти это?

Solutions Collecting From Web of "Поддерживайте работу даже в том случае, если телефон спит?"

Примечание. Это сообщение было обновлено, чтобы включить API JobScheduler в JobScheduler Android Lollipop. Следующее по-прежнему является жизнеспособным способом, но может считаться устаревшим, если вы нацеливаете Android Lollipop и дальше. См. Вторую половину альтернативы JobScheduler .

Один из способов выполнения текущих задач – это:

  • Создайте класс AlarmReceiver

     public class AlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Intent myService = new Intent(context, YourService.class); context.startService(myService); } } 

    С YourService являющимся вашим сервисом 😉

Если вам нужна блокировка WakefulBroadcastReceiver за вашей WakefulBroadcastReceiver рекомендуется продлить действие от WakefulBroadcastReceiver . Не забудьте добавить разрешение WAKE_LOCK в ваш манифест в этом случае!

  • Создать ожидающий намек

Чтобы начать повторный опрос, выполните этот код в своей деятельности:

 Intent myAlarm = new Intent(getApplicationContext(), AlarmReceiver.class); //myAlarm.putExtra("project_id", project_id); //Put Extra if needed PendingIntent recurringAlarm = PendingIntent.getBroadcast(getApplicationContext(), 0, myAlarm, PendingIntent.FLAG_CANCEL_CURRENT); AlarmManager alarms = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE); Calendar updateTime = Calendar.getInstance(); //updateTime.setWhatever(0); //set time to start first occurence of alarm alarms.setInexactRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), AlarmManager.INTERVAL_DAY, recurringAlarm); //you can modify the interval of course 

Этот код устанавливает alarm и доступный pendingIntent . alarmManager получает задание, чтобы повторять alarmManager каждый день (третий аргумент), но неточно, поэтому процессор просыпается примерно после интервала, но не точно (он позволяет ОС выбирать оптимальное время, что уменьшает разряд батареи). При первом запуске будильника (и, таким образом, службы) будет updateTime .

  • Последнее, но не менее важное: вот как убить повторяющуюся тревогу

     Intent myAlarm = new Intent(getApplicationContext(), AlarmReceiver.class); //myAlarm.putExtra("project_id",project_id); //put the SAME extras PendingIntent recurringAlarm = PendingIntent.getBroadcast(getApplicationContext(), 0, myAlarm, PendingIntent.FLAG_CANCEL_CURRENT); AlarmManager alarms = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE); alarms.cancel(recurringAlarm); 

Этот код создает копию вашего (возможно) существующего аварийного сигнала и сообщает alarmManager отменить все аварийные сигналы такого типа.

  • Конечно, в Manifest есть что-то сделать:

Включают эти две строки

  < receiver android:name=".AlarmReceiver"></receiver> < service android:name=".YourService"></service> 

Внутри < application> -tag. Без этого система не принимает начало повторяющегося аварийного сигнала службы.


Начиная с выпуска Android Lollipop , есть новый способ решения этой задачи элегантно. Это также облегчает выполнение только одного действия, если выполняются определенные критерии, такие как состояние сети.

 // wrap your stuff in a componentName ComponentName mServiceComponent = new ComponentName(context, MyJobService.class); // set up conditions for the job JobInfo task = JobInfo.Builder(mJobId, mServiceComponent) .setPeriodic(mIntervalMillis) .setRequiresCharging(true) // default is "false" .setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED) // Parameter may be "ANY", "NONE" (=default) or "UNMETERED" .build(); // inform the system of the job JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); jobScheduler.schedule(task); 

Вы также можете setOverrideDeadline(maxExecutionDelayMillis) крайний срок с помощью setOverrideDeadline(maxExecutionDelayMillis) .

Чтобы избавиться от такой задачи, просто вызовите jobScheduler.cancel(mJobId); Или jobScheduler.cancelAll(); ,

Я бы рекомендовал, если вы создаете это приложение с самого начала, чтобы использовать серверный компонент (да, также нужен мониторинг!) И отправлять push-уведомления, опрос никогда не является надежным решением.