Android 8.0: java.lang.IllegalStateException: не разрешено запускать намерение службы

При запуске приложения приложение запускает службу, которая должна выполнять некоторые сетевые задачи. После нацеливания на уровень API 26 мое приложение не запускает службу на Android 8.0 в фоновом режиме.

Вызвано: java.lang.IllegalStateException: не разрешено запускать службу Намерение {cmp = my.app.tt / com.my.service}: приложение находится в фоновом режиме uid UidRecord {90372b1 u0a136 CEM idle procs: 1 seq (0,0 , 0)}

насколько я понимаю, это относится к: ограничениям фонового выполнения < / а>

Метод startService () теперь выдает исключение IllegalStateException, если приложение, ориентированное на Android 8.0, пытается использовать этот метод в ситуации, когда ему не разрешено создавать фоновые службы.

«в ситуации, когда это не разрешено» - что это на самом деле означает ?? И как это исправить. Я не хочу, чтобы моя служба была "на переднем плане"


person phnmnn    schedule 27.09.2017    source источник
comment
Это означает, что вы не можете запустить службу, когда ваше приложение находится в фоновом режиме.   -  person Tim    schedule 27.09.2017
comment
Возможно, вам потребуется запросить разрешения во время выполнения.   -  person Tigger    schedule 27.09.2017
comment
попробуйте диспетчер заданий firebase.   -  person Mehta    schedule 27.09.2017
comment
это не имеет ничего общего с разрешениями времени выполнения   -  person Tim    schedule 27.09.2017
comment
Используйте startForegroundService() вместо startService().   -  person frogatto    schedule 11.10.2017
comment
Вы можете попробовать использовать targetSdkVersion 25, но скомпилировать с compileSdkVersion 26. Таким образом, вы можете использовать новые классы из Android 8 и новейшую библиотеку поддержки, но ваше приложение не будет ограничено лимитами фонового выполнения.   -  person Kacper Dziubek    schedule 19.01.2018
comment
@KacperDziubek Это должно сработать, но это временное решение, так как осенью 2018 года потребуется настроить таргетинг на SDK26.   -  person RightHandedMonkey    schedule 09.06.2018
comment
@RightHandedMonkey Да, это правда. Когда я писал этот комментарий, еще не было объявлено, что Google Play не позволит обновлять приложения, ориентированные ниже SDK 26.   -  person Kacper Dziubek    schedule 12.06.2018
comment
проверьте этот ответ stackoverflow.com/a/52236155/6401241   -  person Radesh    schedule 08.09.2018
comment
Я получаю исключение на Android 8, даже если уменьшу цель и скомпилирую SDK до 25 (или 23, если на то пошло). Могу ли я сделать какое-то другое временное решение, пока я не перепишу свои приложения, которые будут работать на моих телефонах с Android 8? (Мне нужно серьезно переписать текст, но пока нам понадобятся приложения.)   -  person soger    schedule 06.03.2019
comment
Я не знаю, что, черт возьми, происходило с этим проектом, но я удалил его, воссоздал все заново, и теперь он работает. Это просто жалко.   -  person soger    schedule 06.03.2019
comment
У меня аналогичная проблема, и она была исправлена ​​добавлением setComponent (MYSERVICE) в начальное намерение. Однако я не тестировал его с уровнем API 28.   -  person user2305886    schedule 12.07.2019
comment
Для фоновых операций рекомендуется использовать JobScheduler с Android O и выше. stackoverflow.com/a/54570275/5217859   -  person abhi.nalavade    schedule 29.07.2019


Ответы (18)


Разрешенные ситуации - это временный белый список, в котором фоновая служба ведет себя так же, как и до Android O.

При определенных обстоятельствах фоновое приложение помещается во временный белый список на несколько минут. Пока приложение находится в белом списке, оно может запускать службы без ограничений, а его фоновые службы разрешены. Приложение помещается в белый список, когда оно обрабатывает задачу, видимую пользователю, например:

  • Обработка высокоприоритетного сообщения Firebase Cloud Messaging (FCM).
  • Получение широковещательной рассылки, например сообщения SMS / MMS.
  • Выполнение PendingIntent из уведомления.
  • Запуск службы VpnService до того, как приложение VPN выйдет на передний план.

Источник: https://developer.android.com/about/versions/oreo/background.html

Другими словами, если ваша фоновая служба не соответствует требованиям белого списка, вы должны использовать новый Планировщик заданий. По сути, это то же самое, что и фоновая служба, но она вызывается периодически, а не постоянно в фоновом режиме.

Если вы используете IntentService, вы можете перейти на JobIntentService. См. ответ @ kosev ниже.

person Murat Karagöz    schedule 27.09.2017
comment
Я получаю сбой после того, как хочу запустить службу сразу после получения сообщения GCM с высокой приоритетностью. Я все еще использую GCM: com.google.android.gms: play-services-gcm: 11.4.2, а не com.google.firebase: firebase-messaging: 11.4.2. Не уверен, что это важно ... - person Alex Radzishevsky; 30.10.2017
comment
По сути, это то же самое, что и фоновая служба, но она вызывается периодически, а не постоянно в фоновом режиме. - не уверен, что вы имеете в виду, поскольку службы Android никогда не выполнялись непрерывно. Они запускаются, бегут, затем выключаются. - person Melllvar; 07.11.2017
comment
Является ли FirebaseInstanceIdService и его onTokenRefresh метод высокоприоритетным сообщением FCM? - person Cord Rehn; 28.11.2017
comment
@phnmnn нет, GCMTaskService на самом деле не следует FCM, поэтому они не работают. - person Abhinav Upadhyay; 20.01.2018
comment
@CordRehn да, FirebaseInstanceIdService будет работать, ничего страшного. Следуйте надлежащей документации здесь - person Abhinav Upadhyay; 20.01.2018
comment
Самый простой способ использовать новый JobScheduler - через JobIntentService. Смотрите мой ответ. - person kosev; 15.04.2018
comment
Разве вы не должны использовать WorkManager (здесь: developer.android.com/topic/libraries/architecture / workmanager) вместо JobScheduler или других? Я имею в виду следующее: youtu.be/IrKoBFLwTN0 - person android developer; 04.06.2018
comment
+1. Учитывая тот факт, что получение широковещательной передачи - это ситуация белого списка, отказ от WakefulBroadcastReceiver с обоснованием того, что этот класс больше не является в целом полезным, для меня не имеет смысла, потому что это также BroadcastReceiver. Примечание об устаревании находится здесь: developer.android.com/reference/android/ поддержка / v4 / content / - person Diego dos Santos; 08.08.2018
comment
У меня есть приложение, которое не выполняет ничего из того, что указано в списке для внесения в белый список, и по-прежнему не генерирует никаких исключений, когда оно вызывает startServices () в фоновом режиме. Пожалуйста, проверьте мой вопрос: stackoverflow.com/questions/52316856/ - person makovkastar; 01.10.2018
comment
ТАК неплохо, но меня раньше вводили в заблуждение. Это правда, что я должен использовать JobScheduler? Все люди что-то говорят о startForegroundService / startForeground? - person Gerry; 07.03.2019

У меня есть решение. Для устройств до версии 8.0 вам нужно просто использовать startService(), но для устройств после версии 7.0 вы должны использовать startForgroundService(). Вот пример кода для запуска службы.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        context.startForegroundService(new Intent(context, ServedService.class));
    } else {
        context.startService(new Intent(context, ServedService.class));
    }

А в классе обслуживания добавьте приведенный ниже код для уведомления:

@Override
public void onCreate() {
    super.onCreate();
    startForeground(1,new Notification());
}

Где O - Android версии 26.

Если вы не хотите, чтобы ваша служба запускалась на переднем плане, а вместо этого хотите, чтобы она работала в фоновом режиме, опубликуйте Android O, вы должны привязать службу к соединению, как показано ниже:

Intent serviceIntent = new Intent(context, ServedService.class);
context.startService(serviceIntent);
context.bindService(serviceIntent, new ServiceConnection() {
     @Override
     public void onServiceConnected(ComponentName name, IBinder service) {
         //retrieve an instance of the service here from the IBinder returned 
         //from the onBind method to communicate with 
     }

     @Override
     public void onServiceDisconnected(ComponentName name) {
     }
}, Context.BIND_AUTO_CREATE);
person Sagar Kacha    schedule 05.12.2017
comment
Служба переднего плана - это то, о чем пользователь будет знать, и для чего требуется уведомление. Также будет ANR, если он будет работать слишком долго. Так что это не совсем подходящий ответ, если приложение уже работает в фоновом режиме. - person SimonH; 19.12.2017
comment
Вместо нее можно использовать ContextCompat.startForegroundService(...) в вспомогательной библиотеке. - person jayeffkay; 28.12.2017
comment
Это не решение. - person JacksOnF1re; 09.01.2018
comment
android.app.RemoteServiceException: Context.startForegroundService () затем не вызывал Service.startForeground () - person Choletski; 12.02.2018
comment
Я также согласен, что это не решение. Это обходной путь, и он помогает, но ограничения фона в Oreo были введены не просто так. Такой обход этих ограничений определенно не является правильным подходом (хотя он и работает). Лучше всего использовать JobScheduler (см. Принятый ответ). - person Vratislav Jindra; 12.02.2018
comment
android.app.RemoteServiceException: Плохое уведомление для startForeground: java.lang.RuntimeException: недопустимый канал для служебного уведомления: Уведомление (канал = null pri = 0 contentView = null vibrate = null звук = null по умолчанию = 0x0 flags = 0x40 color = 0x00000000 vis = ЧАСТНЫЙ) - person Vishal Patoliya ツ; 28.03.2018
comment
Я не думаю, что пользователям будет удобно, если вы должны показывать пустое уведомление переднего плана. Учитывая тот факт, что ты должен. - В Android 8.0 представлен новый метод startForegroundService () для запуска новой службы на переднем плане. После того, как система создала службу, у приложения есть пять секунд для вызова метода startForeground () службы, чтобы показать видимое пользователю уведомление новой службы. Если приложение не вызывает startForeground () в течение установленного времени, система останавливает службу и объявляет приложение как ANR. - person heeleeaz; 01.05.2018
comment
Спасибо, это решило мою проблему. Хотя нам следует подумать о том, чтобы перейти к JobIntentService, как описано в других ответах! - person yUdoDis; 23.07.2018
comment
Похоже, new Notificaction() не работает с Android 8.1; Вы должны создать канал для уведомлений: stackoverflow.com/a/47533338/1048087 - person Prizoff; 29.07.2018
comment
Кроме того, из документов: Приложения, предназначенные для API Build.VERSION_CODES.P или более поздней версии, должны запрашивать разрешение Manifest.permission.FOREGROUND_SERVICE, чтобы использовать этот API. - person Prizoff; 29.07.2018
comment
Могу ли я проверить, находится ли приложение на переднем плане или нет? если нет, не запускать службу? - person Pierre; 27.11.2018
comment
Вы не можете запускать службы из фона, а startForegroundService () не работает в Oreo и Pie. Кроме того, у меня возникают сбои в JobScheduler на некоторых устройствах. Workmanager использует планировщик заданий под капотом, так что это не решение для меня. У кого-нибудь есть лучшее решение? - person Prasad Pawar; 02.01.2019
comment
Я нашел это намного лучше, чем планировщик заданий. Что слишком сложно, к тому же я даже не уверен, что он хорошо справляется с тем, что я хочу. Мне просто нужна небольшая служба, которая работает в фоновом режиме и получает какое-то системное уведомление. Планировщик заданий, вероятно, сделает это, но внесет дополнительные задержки. Служба переднего плана OTOH просто дает пользователю короткое ненавязчивое уведомление. Я могу жить с этим. - person VSim; 13.05.2019
comment
Означает ли это, что я должен проверить, соответствует ли API ›= 26, и если да, то вызвать startForegroundService(), иначе вызвать startService()? - person scarface; 17.05.2019
comment
именно этот подход даст вам ошибку: Плохое уведомление для startForeground: java.lang.RuntimeException: недопустимый канал для уведомления службы: null - person Tamim Attafi; 01.01.2020
comment
Я думаю, это зависит от обстоятельств. Например, если вы работаете с сокетами, обходным путем является решение - person Autumn_Cat; 31.03.2020

Лучше всего использовать JobIntentService, который использует новый JobScheduler для Oreo или старые службы, если они недоступны.

Объявите в своем манифесте:

<service android:name=".YourService"
         android:permission="android.permission.BIND_JOB_SERVICE"/>

И в вашем сервисе вы должны заменить onHandleIntent на onHandleWork:

public class YourService extends JobIntentService {

    public static final int JOB_ID = 1;

    public static void enqueueWork(Context context, Intent work) {
        enqueueWork(context, YourService.class, JOB_ID, work);
    }

    @Override
    protected void onHandleWork(@NonNull Intent intent) {
        // your code
    }

}

Затем вы начинаете свою службу с:

YourService.enqueueWork(context, new Intent());
person kosev    schedule 15.04.2018
comment
@ralphgabb developer.android.com/ о / версии / oreo / - person Dr.jacky; 22.05.2018
comment
Как вы можете вызвать нестатический метод внутри статического метода? Не могли бы вы объяснить? - person Malik Motani; 28.09.2018
comment
@Maddy enqueueWork(...) - тоже статический метод. - person hgoebl; 06.10.2018
comment
Куда бы вы позвонили YourService.enqueueWork (context, new Intent ()); ? С приемника вещания? - person TheLearner; 29.10.2018
comment
Я не верю, что это самое простое решение. См. Мой комментарий о WorkManager ниже. При необходимости он использует JobIntentService, но в нем намного меньше шаблонов. - person TALE; 07.03.2019

Если служба работает в фоновом потоке, расширив IntentService, вы можете заменить IntentService на JobIntentService, который предоставляется как часть библиотеки поддержки Android.

Преимущество использования JobIntentService в том, что он ведет себя как IntentService на устройствах pre-O и на O и выше, он отправляет его как задание

JobScheduler также может использоваться для периодических работ / работ по требованию. Но не забудьте обеспечить обратную совместимость, поскольку JobScheduler API доступен только из API 21

person Harini S    schedule 07.12.2017
comment
Проблема с JobIntentService заключается в том, что Android может планировать вашу работу довольно произвольно, и ее нельзя запускать неявно, не доработав, в отличие от IntentService. См. stackoverflow.com/questions/52479262/ - person kilokahn; 04.01.2019

Да, это потому, что вы больше не можете запускать службы в фоновом режиме на API 26. Таким образом, вы можете запускать ForegroundService выше API 26.

Вам придется использовать

ContextCompat.startForegroundService(...)

и опубликуйте уведомление при обработке утечки.

person P.K    schedule 07.05.2018
comment
ОП специально сказал, что он не хочет быть на переднем плане. Это должно быть добавлено как комментарий или как часть более полного ответа. - person Ricardo A.; 27.12.2019

В Oreo Android определены ограничения для фоновых служб .

Чтобы улучшить взаимодействие с пользователем, Android 8.0 (уровень API 26) накладывает ограничения на то, что приложения могут делать при работе в фоновом режиме.

Тем не менее, если вам нужна постоянно работающая служба, вы можете использовать службу переднего плана.

Ограничения фоновых служб. Когда приложение находится в режиме ожидания, существуют ограничения на использование им фоновых служб. Это не относится к службам переднего плана, которые более заметны для пользователя.

Таким образом, вы можете создать службу переднего плана. Вам нужно будет показать уведомление пользователю, когда ваша служба запущена. См. этот ответ (есть много других)

Решение, если -

вы не хотите получать уведомления о ваших услугах?

Вы можете создавать периодические задачи: 1. он запускает вашу службу, 2. служба выполняет свою работу и 3. останавливается. Таким образом, ваше приложение не будет считаться разряженным.

Вы можете использовать периодическую задачу с помощью Alarm Manager, Планировщик заданий, Evernote-Jobs или Диспетчер работы.

Я протестировал постоянно работающую службу с помощью Work-Manager.

person Khemraj Sharma    schedule 08.02.2019
comment
WorkManager кажется лучшим вариантом, если предположить, что работа не должна выполняться немедленно. Он обратно совместим с API 14, использует JobScheduler на устройствах с API 23+ и комбинацию BroadcastReceiver + AlarmManager на устройствах с API 14-22. - person James Allen; 19.06.2019
comment
Ключевым моментом в WorkManager является то, что WorkManager предназначен для задач, которые можно отложить, то есть не требуется для немедленного выполнения - person touhid udoy; 19.07.2019

Как сказал @kosev в его ответе, вы можете использовать JobIntentService. Но я использую альтернативное решение - ловлю IllegalStateException и запускаю службу как передний план. Например, эта функция запускает мою службу:

@JvmStatic
protected fun startService(intentAction: String, serviceType: Class<*>, intentExtraSetup: (Intent) -> Unit) {
    val context = App.context
    val intent = Intent(context, serviceType)
    intent.action = intentAction
    intentExtraSetup(intent)
    intent.putExtra(NEED_FOREGROUND_KEY, false)

    try {
        context.startService(intent)
    }
    catch (ex: IllegalStateException) {
        intent.putExtra(NEED_FOREGROUND_KEY, true)
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            context.startForegroundService(intent)
        }
        else {
            context.startService(intent)
        }
    }
}

и когда я обрабатываю Intent, я делаю такую ​​вещь:

override fun onHandleIntent(intent: Intent?) {
    val needToMoveToForeground = intent?.getBooleanExtra(NEED_FOREGROUND_KEY, false) ?: false
    if(needToMoveToForeground) {
        val notification = notificationService.createSyncServiceNotification()
        startForeground(notification.second, notification.first)

        isInForeground = true
    }

    intent?.let {
        getTask(it)?.process()
    }
}
person Alex Shevelev    schedule 07.03.2019
comment
Мне нравится твое решение. Для меня это решение, потому что иногда context.startService работает в фоновом режиме - иногда нет - это выглядит как единственный лучший способ, иначе вам придется реализовать больше кода в своем основном классе extending Application и implementing ActivityLifecycleCallbacks и отслеживать, находится ли приложение на переднем плане или в фоновом режиме и соответственно начните свое намерение. - person Pierre; 15.05.2019
comment
Можно ли отловить это исключение? - person thecr0w; 10.01.2020
comment
есть одна потенциальная ошибка - пока context.startService(intent) пойман try/catch в блоке try, в блоке catch еще раз повторяется та же строка кода, что потенциально может вызвать сбой. - person Stan; 05.03.2021

В примечаниях к выпуску firebase говорится, что поддержка Android O впервые появилась в 10.2.1 (хотя я бы рекомендовал использовать самую последнюю версию).

пожалуйста, добавьте новые зависимости обмена сообщениями firebase для Android O

compile 'com.google.firebase:firebase-messaging:11.6.2'

при необходимости обновите сервисы Google Play и репозитории Google.

person Dhaval Jivani    schedule 13.12.2017
comment
Это не отвечает на вопрос, и вопрос не имеет ничего общего с firebase. Это следует поставить в качестве комментария. - person Ricardo A.; 27.12.2019

Я вижу много ответов, в которых рекомендуется просто использовать ForegroundService. Чтобы использовать ForegroundService, с ним должно быть связано уведомление. Пользователи увидят это уведомление. В зависимости от ситуации они могут рассердиться на ваше приложение и удалить его.

Самое простое решение - использовать новый компонент архитектуры под названием WorkManager. Вы можете ознакомиться с документацией здесь: https://developer.android.com/topic/libraries/architecture/workmanager/

Вы просто определяете свой рабочий класс, который расширяет Worker.

public class CompressWorker extends Worker {

    public CompressWorker(
        @NonNull Context context,
        @NonNull WorkerParameters params) {
        super(context, params);
    }

    @Override
    public Worker.Result doWork() {

        // Do the work here--in this case, compress the stored images.
        // In this example no parameters are passed; the task is
        // assumed to be "compress the whole library."
        myCompress();

        // Indicate success or failure with your return value:
        return Result.SUCCESS;

        // (Returning RETRY tells WorkManager to try this task again
        // later; FAILURE says not to try again.)
    }
}

Затем вы планируете, когда хотите его запустить.

    OneTimeWorkRequest compressionWork = 
        new OneTimeWorkRequest.Builder(CompressWorker.class)
            .build();
    WorkManager.getInstance().enqueue(compressionWork);

Легкий! Есть много способов настроить воркеров. Он поддерживает повторяющиеся задания, и вы даже можете выполнять сложные вещи, например, цепочку, если вам это нужно. Надеюсь это поможет.

person TALE    schedule 14.11.2018
comment
В настоящее время WorkManager все еще находится в стадии альфа-версии. - person pzulw; 14.11.2018
comment
5 марта 2019 г. - стабильный выпуск WorkManager 1.0.0. - person phnmnn; 07.03.2019
comment
следует использовать WorkManager вместо использования interservice или JobIntentService - person sivaBE35; 25.03.2019
comment
_1 _... это может быть проще всего, однако моему приложению нужна фоновая служба, которая немедленно выполняет запросы пользователей! - person Someone Somewhere; 09.05.2019
comment
Если вам требуется, чтобы задача была завершена немедленно, вам следует использовать службу переднего плана. Пользователь увидит уведомление и узнает, что вы выполняете работу. Ознакомьтесь с документацией, если вам нужна помощь в выборе, что использовать. У них есть неплохое руководство по фоновой обработке. developer.android.com/guide/background - person TALE; 09.05.2019

Если какое-либо намерение ранее работало нормально, когда приложение находилось в фоновом режиме, это больше не будет иметь место в Android 8 и выше. Имеется в виду только намерение, которое должно выполнить некоторую обработку, когда приложение находится в фоновом режиме.

Необходимо выполнить следующие шаги:

  1. Вышеупомянутое намерение должно использовать JobIntentService вместо IntentService.
  2. Класс, расширяющий JobIntentService, должен реализовывать метод - onHandleWork(@NonNull Intent intent) и должен располагаться ниже метода, который будет вызывать метод onHandleWork:

    public static void enqueueWork(Context context, Intent work) {
        enqueueWork(context, xyz.class, 123, work);
    }
    
  3. Вызов enqueueWork(Context, intent) из класса, в котором определено ваше намерение.

    Образец кода:

    Public class A {
    ...
    ...
        Intent intent = new Intent(Context, B.class);
        //startService(intent); 
        B.enqueueWork(Context, intent);
    }
    

Приведенный ниже класс ранее расширял класс обслуживания

Public Class B extends JobIntentService{
...

    public static void enqueueWork(Context context, Intent work) {
        enqueueWork(context, B.class, JobId, work);
    }

    protected void onHandleWork(@NonNull Intent intent) {
        ...
        ...
    }
}
  1. com.android.support:support-compat нужен для JobIntentService - я использую 26.1.0 V.

  2. Самое важное - убедиться, что версия библиотек Firebase установлена ​​как минимум на 10.2.1, у меня были проблемы с 10.2.0 - если они у вас есть!

  3. Ваш манифест должен иметь разрешение ниже для класса Service:

    service android:name=".B"
    android:exported="false"
    android:permission="android.permission.BIND_JOB_SERVICE"
    

Надеюсь это поможет.

person c_c    schedule 15.02.2019

Альтернативное решение с помощью JobScheduler, он может запускать службу в фоновом режиме через равные промежутки времени.

Сначала создайте класс с именем Util.java

import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;

public class Util {
// schedule the start of the service every 10 - 30 seconds
public static void schedulerJob(Context context) {
    ComponentName serviceComponent = new ComponentName(context,TestJobService.class);
    JobInfo.Builder builder = new JobInfo.Builder(0,serviceComponent);
    builder.setMinimumLatency(1*1000);    // wait at least
    builder.setOverrideDeadline(3*1000);  //delay time
    builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);  // require unmetered network
    builder.setRequiresCharging(false);  // we don't care if the device is charging or not
    builder.setRequiresDeviceIdle(true); // device should be idle
    System.out.println("(scheduler Job");

    JobScheduler jobScheduler = null;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
        jobScheduler = context.getSystemService(JobScheduler.class);
    }
    jobScheduler.schedule(builder.build());
   }
  }

Затем создайте класс JobService с именем TestJobService.java.

import android.app.job.JobParameters;
import android.app.job.JobService;
import android.widget.Toast;
 
  /**
   * JobService to be scheduled by the JobScheduler.
   * start another service
   */ 
public class TestJobService extends JobService {
@Override
public boolean onStartJob(JobParameters params) {
    Util.schedulerJob(getApplicationContext()); // reschedule the job
    Toast.makeText(this, "Bg Service", Toast.LENGTH_SHORT).show();
    return true;
}

@Override
public boolean onStopJob(JobParameters params) {
    return true;
  }
 }

После этого класса BroadCast Receiver с именем ServiceReceiver.java

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

 public class ServiceReceiver extends BroadcastReceiver {
 @Override
public void onReceive(Context context, Intent intent) {
    Util.schedulerJob(context);
 }
}

Обновите файл манифеста, указав код класса службы и получателя.

<receiver android:name=".ServiceReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
    <service
        android:name=".TestJobService"
        android:label="Word service"
        android:permission="android.permission.BIND_JOB_SERVICE" >

    </service>

Левый модуль запуска main_intent в файл mainActivity.java, который создается по умолчанию, а изменения в файле MainActivity.java вносятся

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Util.schedulerJob(getApplicationContext());
  }
 }

УУААХ !! Фоновая служба запускается без службы переднего плана

[Изменить]: Диспетчер работ можно использовать для любого типа фоновых задач в Android.

person Anshul1507    schedule 27.08.2019

Если вы запускаете свой код на 8.0, приложение выйдет из строя. Так что запустите службу на переднем плане. Если ниже 8.0 используйте это:

Intent serviceIntent = new Intent(context, RingtonePlayingService.class);
context.startService(serviceIntent);

Если выше или 8.0, используйте это:

Intent serviceIntent = new Intent(context, RingtonePlayingService.class);
ContextCompat.startForegroundService(context, serviceIntent );
person iamfaizuddin    schedule 18.09.2018
comment
Рекомендуется использовать службы Foreground только в тех случаях, когда пользователю необходимо знать, что служба запущена. Типичный пример - воспроизведение музыки в фоновом режиме. Есть и другие случаи, которые имеют смысл, но вам не следует просто преобразовывать все свои службы в службы Foreground. Подумайте о преобразовании ваших сервисов для использования WorkManager из архитектурных компонентов Google, когда вам просто нужно поработать в фоновом режиме и быть уверенным, что он будет работать. - person TALE; 14.11.2018
comment
startForegroundService требует разрешения, иначе java.lang.SecurityException: Permission Denial: startForeground from pid=13708, uid=10087 requires android.permission.FOREGROUND_SERVICE. Исправьте на stackoverflow.com/a/52382711/550471 - person Someone Somewhere; 09.05.2019

Из-за неоднозначного количества голосов по этому ответу (+ 4 / -4 на данный момент), ПОЖАЛУЙСТА, ПОСМОТРИТЕ Вначале НА ДРУГИЕ ОТВЕТЫ И ИСПОЛЬЗУЙТЕ ЭТО ТОЛЬКО В КАЧЕСТВЕ ПОСЛЕДНЕГО КУРОРТА. Я использовал это один раз для сетевого приложения, которое запускается от имени пользователя root и я согласен с общим мнением, что это решение не следует использовать при нормальных обстоятельствах.

Оригинальный ответ ниже:

Все остальные ответы верны, но я хотел бы указать, что еще один способ обойти это - попросить пользователя отключить оптимизацию батареи для вашего приложения (обычно это не очень хорошая идея, если ваше приложение не связано с системой). См. этот ответ, чтобы узнать, как запросить отказ от оптимизации заряда батареи без блокировки вашего приложения в Google Play.

Вы также должны проверить, отключена ли оптимизация батареи в вашем приемнике, чтобы предотвратить сбои через:

if (Build.VERSION.SDK_INT < 26 || getSystemService<PowerManager>()
        ?.isIgnoringBatteryOptimizations(packageName) != false) {
    startService(Intent(context, MyService::class.java))
} // else calling startService will result in crash
person Mygod    schedule 22.07.2018
comment
Просить пользователей предоставить вам бесплатный пропуск, используя как можно больше батареи, - не лучшее решение. Подумайте о преобразовании вашего кода в более экономичное решение. Ваши пользователи будут вам благодарны. - person TALE; 14.11.2018
comment
@TALE Не все фоновые службы можно сделать более экономичными, используя JobScheduler и прочее. Некоторые приложения должны работать на более низком уровне, чем обычные приложения для синхронизации. Это альтернативное решение, если оно не работает. - person Mygod; 15.11.2018

если у вас есть встроенное push-уведомление для обмена сообщениями firebase, тогда,

Добавить новые / обновить зависимости обмена сообщениями firebase для Android O (Android 8.0) из-за фона Пределы выполнения.

compile 'com.google.firebase:firebase-messaging:11.4.0'

при необходимости обновите сервисы Google Play и репозитории Google.

Обновление:

 compile 'com.google.firebase:firebase-messaging:11.4.2'
person Samir Mangroliya    schedule 04.10.2017

Используйте startForegroundService() вместо startService() и не забудьте создать startForeground(1,new Notification()); в своей службе в течение 5 секунд после запуска службы.

person Arpit    schedule 21.03.2018
comment
Похоже, что новый Notificaction () не работает с Android 8.1; Вы должны создать канал для уведомлений: stackoverflow.com/a/47533338/1048087 - person Prizoff; 29.07.2018

У меня тоже была эта пробема

добавил эту библиотеку

implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'

и переустановил приложение, решило это для меня

person Parikshit Sharma    schedule 24.06.2020

на самом деле это происходит из-за того, что телефон находится вне экрана или вы нажали кнопку питания при запуске службы. Решение, которое сработало для меня, - запустить действие, и когда оно войдет в onResume, запустите службу. в моем случае это была загрузка и запуск службы.

person Pranay'z' Vlogs    schedule 26.01.2021

не используйте в onStartCommand:

return START_NOT_STICKY

просто измените его на:

return START_STICKY

и это будет работать

person Omar Othman    schedule 01.05.2018