Эта проблема может возникать только на устройствах под управлением Oreo или более поздней версии, поскольку у меня есть только OnePlus 3T для разработки.
У меня есть передний план Service
, которыйначал использовать ContextCompat#startForegroundService()
и в методе startCommand
службы я не забудьте создать / включить мой канал уведомлений , чтобы я мог позвонить startForeground
с соответствующим текущим уведомлением.Поэтому я считаю, что с точки зрения требований, я все понимаю здесь.
Что делает мой Foreground Service
:
- Он действует как Bluetooth-сервер , используяBluetooth Class RFCOMM BSPP для прослушивания подключения клиента;
- Когда клиент подключается, он прослушивает входящие запросы;
- Он выполняет запросы и соответственно отправляет данные.
Моя проблема заключается в последнем пункте.Когда я подключаюсь и прошу отправить данные, на телефоне происходит две вещи:
- Соответствующие данные загружаются с телефона и
- После полной загрузки данные отправляются наклиент.
Каждая из этих операций имеет свои собственные уведомления для отображения хода выполнения для конечного пользователя.
Хотя первая операция не задерживается, вторая может занять много минут(до 6 в одном из моих тестов).
После дальнейших тестов причиной являются уведомления, потому что я отменяю уведомление о первой операции, затем вызываю вторую операцию, которая, в свою очередь, отображает и обновляет свое собственное уведомление.
В итоге, поскольку я вызываю NotificationManagerCompat.cancel
в уведомлении о первой операции непосредственно перед вызовом второй операции, этот вызов может быть отложен на много времени.Если я сначала не отменю уведомление, то сразу же начнется вторая операция.
В качестве решения я полагал, что за такое поведение отвечает режим Doze, поэтому я вручную внес белый список в мое приложение: аккумулятороптимизация настроек моего телефона.Это ничего не изменило.
Наконец, если в какой-то момент я разблокирую свой телефон / включаю экран, уведомления о блокировке / задержке немедленно разблокируются, и второй процесс запускается прямо на лету.Так что, конечно, такое поведение не происходит, когда мой телефон подключен к компьютеру даже с выключенным экраном.
Это ошибка?Это связано с режимом дремоты?Я не знаю.
[Изменить 1]
Для большей наглядности приведен фрагмент кода, представляющий последовательность операций:
loadData() {
... // defer heavy work on a worker thread and updates notification of progress from time to time (every 10%)
notifyDataLoadingStarted(); // on main thread. Displays its notification with progress bar
}
// once the data is fully loaded
onDataLoaded() { // called on the main thread
cancelDataLoadNotification(); // asks the notification manager compat to cancel notification
initiateDataSendingOperation(); // will also defer heavy work on a worker thread and update its notification accordingly
}
В результате onDataLoaded
вызывается после завершения первой операции.Но проблема в том, что cancelDataLoadNotification
блокирует.Я нахожусь в главном потоке, и этот метод возвращается очень и очень в последнее время.Следовательно, по этой причине initiateDataSendingOperation
сильно задерживается.
Когда я разблокирую свой телефон, я вижу, что уведомление об операции загрузки застряло в середине, как будто операция загрузки остановлена,около 50%.Тем не менее, это длится всего доли секунды, потому что, прежде чем я знаю, первое уведомление выскакивает, а второе появляется. Все в мгновение ока.Что ясно означает, что да, первая операция действительно закончилась давным-давно, но ее уведомление определенно устарело.А поскольку вторая операция будет инициирована только при отмене первого уведомления, из них можно четко понять, что вторая операция сильно задерживается.
Вот почему мой первый обходной путь работает, если я сначала запускаю вторую операцию перед отменой уведомления о первой операции.
Тем не менее, в любом случае уведомления все еще устарели, пока экран выключен.