При запуске приложения приложение запускает службу, которая должна выполнять некоторые сетевые задачи. После нацеливания на уровень API 26 моему приложению не удается запустить службу на Android 8.0 в фоновом режиме.
Вызвано: java.lang.IllegalStateException: не разрешено запускать службу. Намерение {cmp = my.app.tt / com.my.service}: приложение находится в фоновом режиме uid UidRecord {90372b1 u0a136 CEM бездействует: 1 сек (0,0 , 0)}
насколько я понимаю, это связано с: Фоновые пределы выполнения
Метод startService () теперь генерирует исключение IllegalStateException, если приложение, ориентированное на Android 8.0, пытается использовать этот метод в ситуации, когда ему не разрешено создавать фоновые службы.
« в ситуации, когда это не разрешено » - что это на самом деле значит ?? И как это исправить. Я не хочу устанавливать свой сервис как "передний план"
startForegroundService()
вместоstartService()
.Ответы:
Разрешенные ситуации - это временный белый список, в котором фоновая служба работает так же, как и до Android O.
Источник: https://developer.android.com/about/versions/oreo/background.html
Другими словами, если ваша фоновая служба не соответствует требованиям белого списка, вы должны использовать новый JobScheduler . По сути, это то же самое, что и фоновая служба, но она вызывается периодически, а не работает в фоновом режиме.
Если вы используете IntentService, вы можете перейти на JobIntentService. Смотрите ответ @ kosev ниже .
источник
FirebaseInstanceIdService
и егоonTokenRefresh
метод высокоприоритетным сообщением FCM?Я получил решение. Для устройств до 8.0 вы должны просто использовать
startService()
, но для устройств после 7.0, вы должны использоватьstartForgroundService()
. Вот пример кода для запуска сервиса.А в классе обслуживания, пожалуйста, добавьте код ниже для уведомления:
Где O - версия для Android 26.
источник
ContextCompat.startForegroundService(...)
библиотека поддержки, которую можно использовать вместо.Лучший способ - использовать JobIntentService, который использует новый JobScheduler для Oreo или старые сервисы, если они недоступны.
Объявите в своем манифесте:
И в вашем сервисе вы должны заменить onHandleIntent на onHandleWork:
Затем вы начинаете свой сервис с:
источник
enqueueWork(...)
является статическим методом.Если служба работает в фоновом потоке за счет расширения
IntentService
, вы можете заменитьIntentService
сJobIntentService
которой осуществляется в рамках Android библиотеки поддержкиПреимущество использования
JobIntentService
заключается в том, что он ведет себя какIntentService
на устройствах pre-O, а на O и выше он отправляет его как задание.JobScheduler
может также использоваться для периодических / по требованию рабочих мест. Но необходимо обеспечить обратную совместимость, так какJobScheduler
API доступен только из API 21источник
В Oreo Android определены ограничения на фоновые сервисы .
Тем не менее, если вам нужен всегда запущенный сервис, вы можете использовать приоритетный сервис.
Таким образом, вы можете сделать передний план обслуживания . Вам нужно будет показать уведомление пользователю, когда ваша служба работает. Смотрите этот ответ (Есть много других)
Решение, если -
Вы не хотите получать уведомления для вашего сервиса?
Вы можете использовать периодическую задачу с сигнализации диспетчера , планировщика заданий , Evernote-Работа или Работа менеджером .
Я тестировал вечно работающий сервис с Work-Manager.
источник
Да, это потому, что вы больше не можете запускать службы в фоновом режиме через API 26. Таким образом, вы можете запустить ForegroundService выше API 26.
Вам придется использовать
и опубликовать уведомление при обработке утечки.
источник
Как сказал @kosev в своем ответе, вы можете использовать JobIntentService. Но я использую альтернативное решение - я ловлю IllegalStateException и запускаю службу в качестве переднего плана. Например, эта функция запускает мой сервис:
и когда я обрабатываю Intent, я делаю следующее:
источник
context.startService
работает в фоновом режиме - иногда нет - это выглядит как единственный лучший способ, в противном случае вам нужно реализовать больше кода в своем основном классеextending Application
иimplementing ActivityLifecycleCallbacks
отслеживать, находится ли приложение на переднем плане или в фоне, и начинать свои намерения. соответственно.В примечаниях к выпуску Firebase говорится , что поддержка Android O была впервые выпущена в 10.2.1 (хотя я бы рекомендовал использовать самую последнюю версию).
пожалуйста, добавьте новые зависимости от сообщений Firebase для Android O
обновить службы Google Play и Google репозитории, если это необходимо.
источник
Если какое-либо намерение ранее работало нормально, когда приложение находится в фоновом режиме, это не будет иметь место больше для Android 8 и выше. Имеется в виду только намерение, которое должно выполнять некоторую обработку, когда приложение находится в фоновом режиме.
Следующие шаги должны быть выполнены:
JobIntentService
вместоIntentService
.Класс, который расширяет,
JobIntentService
должен реализовыватьonHandleWork(@NonNull Intent intent)
метод - и должен иметь метод ниже, который вызоветonHandleWork
метод:Позвоните
enqueueWork(Context, intent)
из класса, где определены ваши намерения.Образец кода:
com.android.support:support-compat
нужен дляJobIntentService
- я использую26.1.0 V
.Самое главное, чтобы версия библиотек Firebase была, по крайней мере
10.2.1
, у меня были проблемы10.2.0
- если у вас есть какие-либо!Ваш манифест должен иметь приведенное ниже разрешение для класса обслуживания:
Надеюсь это поможет.
источник
Я вижу много ответов, которые рекомендуют просто использовать ForegroundService. Чтобы использовать ForegroundService, должно быть уведомление, связанное с ним. Пользователи увидят это уведомление. В зависимости от ситуации они могут раздражать ваше приложение и удалять его.
Самое простое решение - использовать новый компонент архитектуры под названием WorkManager. Вы можете проверить документацию здесь: https://developer.android.com/topic/libraries/architecture/workmanager/
Вы просто определяете свой рабочий класс, который расширяет Worker.
Затем вы планируете, когда вы хотите запустить его.
Легко! Существует множество способов настройки рабочих. Он поддерживает повторяющиеся задания, и вы можете даже делать сложные вещи, такие как цепочка, если вам это нужно. Надеюсь это поможет.
источник
WorkManager is intended for tasks that are deferrable—that is, not required to run immediately
... это может быть проще, но моему приложению нужен фоновый сервис, который немедленно выполняет запросы пользователей!Альтернативное решение с помощью JobScheduler позволяет запускать службу в фоновом режиме через регулярные промежутки времени.
Сначала создайте класс с именем Util.java
Затем сделайте класс JobService с именем TestJobService.java
После этого класс приемника BroadCast с именем ServiceReceiver.java
Обновите файл манифеста с кодом класса обслуживания и получателя.
Оставьте средство запуска main_intent в файле mainActivity.java, который создается по умолчанию, и изменения в файле MainActivity.java
WOOAAH !! Фоновая служба запускается без службы Foreground
источник
Если вы запускаете свой код на 8.0, то приложение будет аварийно завершать работу. Так что запускайте сервис на переднем плане. Если ниже 8.0 используйте это:
Если выше или 8.0, то используйте это:
источник
java.lang.SecurityException: Permission Denial: startForeground from pid=13708, uid=10087 requires android.permission.FOREGROUND_SERVICE
. Исправить на stackoverflow.com/a/52382711/550471если у вас есть встроенное push-уведомление, то
Добавьте новые / обновите зависимости обмена сообщениями Firebase для Android O (Android 8.0), из-за ограничений фонового выполнения .
обновить службы Google Play и Google репозитории, если это необходимо.
Обновить:
источник
Используйте
startForegroundService()
вместоstartService()
и не забудьте создатьstartForeground(1,new Notification());
в своем сервисе в течение 5 секунд с момента запуска сервиса.источник
Из-за неоднозначного голосования по этому ответу (+ 4 / -4 по состоянию на это редактирование), ПОЖАЛУЙСТА, СМОТРИТЕ НА ДРУГИЕ ОТВЕТЫ И ПЕРВЫЙ ИСПОЛЬЗУЙТЕ ЭТО ТОЛЬКО В ПОСЛЕДНЕМ КУРОРТЕ . Я использовал это только один раз для сетевого приложения, работающего от имени пользователя root, и я согласен с общим мнением, что это решение не следует использовать в обычных условиях.
Оригинальный ответ ниже:
Все остальные ответы верны, но я хотел бы отметить, что еще один способ обойти это - попросить пользователя отключить оптимизацию батареи для вашего приложения (обычно это не очень хорошая идея, если ваше приложение не связано с системой). Посмотрите этот ответ, чтобы узнать, как запросить отказ от оптимизации батареи без блокировки приложения в Google Play.
Вам также следует проверить, не отключены ли в вашем приемнике оптимизации батареи, чтобы предотвратить сбои, с помощью:
источник
JobScheduler
и прочее. Некоторые из приложений должны работать на более низком уровне, чем типичные приложения синхронизации. Это альтернативное решение, когда это не работает.не используйте в onStartCommand:
просто измените его на:
и это будет работать
источник