Прежде всего, это длинный вопрос, нацеленный только на одну тему, и мне жаль, что я не могу поделиться каким-либо кодом, поскольку это проект нашей компании и засекречен.Мы используем сервис переднего плана, который выполняет задачу в течение 100 миллисекунд.До тех пор, пока я не задал этот вопрос, мы использовали несколько подходов для выполнения кода за короткий промежуток времени, а именно:
- Поток с "Thread.sleep" в нем (не лучший подход, но это был нашпервая попытка, пошла не согласованно),
- Поток с "Object.wait" (тот же результат, что и выше),
- Таймер (также несовместим и прекращает выполнение после некоторого временивремя),
- ScheduledThreadPoolExecutor , в котором также есть проблема, описанная выше.
На моем телефоне (HUAWEI P20 Lite), попробовав эти подходы, мы наконец-торешил использовать Handler с HandlerThread , поскольку работа не требует взаимодействия с потоком пользовательского интерфейса.(не всегда, но мы используем отдельный обработчик для этого.) Между каждым подходом, это, кажется, наиболее последовательный, однако мы не знаем, зависит ли это от телефона, производителя или чего-либо, мой телефон перестает выполнятьзацикливание обработчика с postDelayed до тех пор, пока я не буду взаимодействовать с пользовательским интерфейсом приложения каким-либо образом, например: касаться уведомления, когда экран включен. Да, я не говорю о нажатии на само уведомление, но даже касаюсьили, как расширение подробного текста, снова запускает обработчик.Это значит, я думаю, что мой телефон пытается сэкономить энергию, приостановив фоновое выполнение.
Теперь мы хотим запускать этот метод только при включенном экране, так как мы уже приостанавливаем сам обработчик через «приемник широковещания с выключенным экраном», который зарегистрирован в службе переднего плана, удаляя обратные вызовывыполнимый, но после запуска экрана, широковещание получено, но даже если выполняется «Handler.post ()», он не запускает выполнимый внутри, следовательно, он никогда не зацикливается.
Чтобы дать вам немного контекстаВот какая у нас логика:
Мы открываем службу переднего плана с чем-то похожим на приведенный ниже код:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
getApplicationContext().startForegroundService(
new Intent(getApplicationContext(),
MyService.class));
}
else
{
getApplicationContext().startService(
new Intent(getApplicationContext(), MyService.class));
}
И затем внутри службы мы делаем что-то вродеследующее:
public int onStartCommand()
{
// notification stuff
HandlerThread thread = new HandlerThread("myThread");
thread.start();
Handler handler = new Handler(thread.getLooper());
handler.post(new Runnable()
{
// do stuff
// this runnable stops executing after some time. This is where the problem lies.
handler.postDelayed(this, 100);
})
return START_STICKY;
}
Обработчик внутри onStartCommand нестабилен, иногда он не учитывает задержку или иногда вообще не выполняется.Теперь, не уважая задержку, это не проблема, поскольку мы не должны быть настолько последовательными, поскольку наши вычисления не зависят от истекшего времени или чего-то еще, но если он прекращает выполнение (что в этом случае, это делает), вот гдепроблема начинается.
Для этого мы будем использовать совершенно новый класс, который предлагает Android Jetpack, WorkManager , который идеально подходит для проверки состояния обработчиков.Чтобы понять, активны ли потоки или нет, мы зарегистрировали время последнего выполнения кода внутри обработчика и собираемся получить к нему доступ через рабочий класс.Теперь, если обработчики не работают, мы хотели бы разбудить эти обработчики.Как это может быть сделано?Потому что помните, это происходит при включенном экране.
Редактировать: Вот несколько журналов о том, как происходит выполнение потока.
//2018-12-19 11:35:15.048 17222-17952/com.example.something D/MyService: threadName: MainThread, postDelayedValue: true
//2018-12-19 11:35:15.154 17222-17952/com.example.something D/MyService: threadName: MainThread, postDelayedValue: true
2018-12-19 11:35:15.262 17222-17952/com.example.something D/MyService: threadName: MainThread, postDelayedValue: true
2018-12-19 11:35:45.262 17222-17952/com.example.something D/MyService: threadName: MainThread, postDelayedValue: true
//2018-12-19 11:35:45.365 17222-17952/com.example.something D/MyService: threadName: MainThread, postDelayedValue: true
//2018-12-19 11:35:45.468 17222-17952/com.example.something D/MyService: threadName: MainThread, postDelayedValue: true
Есть предложения?Есть ли обходные пути для этого?Мы ценим любую помощь и комментарий, большое спасибо.