Запуск службы переднего плана, когда приложение имеет фоновый режим на Android Pie - PullRequest
0 голосов
/ 04 октября 2018

В Android 9.0 (Pie) пользователь может запретить вашему приложению выполнять фоновую работу через настройки.Наше приложение обнаружило следующее исключение, когда мы пытаемся запустить службу переднего плана на устройствах Pie, если приложение имеет фоновый режим, даже если активность приложения полностью находится на переднем плане.

RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground()

Мы вызываем startForeground ()в запущенной службе, но системный журнал при попытке запустить службу показывает:

system_process W/ActivityManager: Service.startForeground() not allowed due to bg restriction

Кажется странным получать исключение, когда вы выполняете документированные шаги для служб переднего плана,и система отклоняет приложение от запуска службы переднего плана, когда ваше приложение все еще находится на переднем плане.Мне еще предстоит найти много документации, относящейся к этому, но является ли это документированным поведением?И есть ли у вашего приложения хотя бы способ узнать, ограничен ли он в фоновом режиме, и, следовательно, не пытаться запустить службу на переднем плане?

enter image description here

Мой Сервисный код по сути выглядит следующим образом.Нашей целью является значение 27.

class MyService : Service() {

    override fun onCreate() {
        super.onCreate()
        // create notification
        startForeground(NOTIFICATION_ID, notification)
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        if (intent == null || intent.action == null || intent.action == ACTION_STOP) {
            quit()
        }
        doWork()
        return START_NOT_STICKY
    }

    override fun onBind(intent: Intent?): IBinder? {
        return null
    }

    override fun onTaskRemoved(rootIntent: Intent?) {
        super.onTaskRemoved(rootIntent)
        quit()
    }

    private fun quit() {
        stopForeground(true)
        stopSelf()
    }

    companion object {

        fun start(context: Context) {
            val intent = Intent(context, MyService::class.java)
            intent.action = ACTION_START
            ContextCompat.startForegroundService(context, intent)
        }

        fun stop(context: Context) {
            val intent = Intent(context, MyService::class.java)
            intent.action = ACTION_STOP
            ContextCompat.startForegroundService(context, intent)
        }
    }
}

1 Ответ

0 голосов
/ 05 октября 2018

Понял, что сбой действительно произойдет после второго вызова ContextCompat.startForegroundService () в MyService.stop () , который я использовал для отправки намерения с«stop» Действие для остановки службы вместо вызова context.stopService () .Сначала я думал, что мне нужно вручную вызвать stopForeground () в Сервисе, но вызов context.stopService (), кажется, останавливает службу переднего плана и в любом случае удаляет уведомление и не приводит к сбою, поэтомуЯ решил провести рефакторинг того, как я справляюсь с остановкой службы.

ОБНОВЛЕНИЕ: Я думаю, что дополнительной частью проблемы также была попытка использовать Intents для запуска и остановки службы, особенно потому, что в некоторых случаях моя служба быланачался, а затем остановился слишком быстро.Очень полезная ветка с Яном Лейком дает следующие рекомендации об услугах:

Я бы настоятельно рекомендовал не использовать startService в качестве способа передачи сообщений вашему сервису.Использование EventBus или LocalBroadcastReceiver - намного лучший способ передачи сообщений, не связывая это с действиями жизненного цикла.Я бы также избегал, чтобы внешние компоненты вызывали метод stopService () напрямую - пусть служба сама управляет своим собственным жизненным циклом, реагируя на события, которые вы отправляете.

...