Подтвердить что ты не робот

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

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

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

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

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

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

4b9b3361

Ответ 1

Примечание. Это сообщение было обновлено, чтобы включить API 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. Не забудьте добавить разрешение 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 получает задание, чтобы повторять recurringAlarm каждый день (третий аргумент), но неточно, поэтому процессор просыпается примерно после интервала, но не точно (он позволяет ОС выбирать оптимальное время, что уменьшает разряд батареи), При первом запуске будильника (и, следовательно, службы) будет выбрано 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).

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

Ответ 2

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