Передний план убивают из Орео - PullRequest
0 голосов
/ 20 сентября 2018

Я написал службу переднего плана, которая работает правильно для всех версий ОС ниже, чем Oreo.От Oreo процесс приложения убивается после 5 минут закрытия и удаления приложения из последних.

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

Согласно руководствам по документации для разработчиков.Я следовал приведенным ниже шагам, чтобы запустить службу переднего плана.

  1. Служба переднего плана запускается с помощью startForegroundService() метода
  2. В течение 5 секунд после запуска службы для службы отображается уведомление с использованием startForeground()
  3. Возврат START_STICKY из onStartCommand() из service

Я сталкиваюсь с этой проблемой на следующих телефонах:

  1. OnePlus 5T
  2. Vivo
  3. Oppo
  4. Mi

Что я пытался предотвратить уничтожение службы переднего плана?

  1. Отключить оптимизация батареи для приложения, показывающая системное диалоговое окно для пользователя, чтобы отключить режим ожидания.

Что я пытался перезапустить на переднем плане-сервис?

  1. Используется AlarmManager для перезапуска службы из onTaskRemoved ().Пожалуйста, проверьте эту ссылку для получения более подробной информации.

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

Класс обслуживания переднего плана

    class DataCaptureService : Service() {

        private var isServiceStarted = false

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

override fun onCreate() {
        super.onCreate()
        wakeLock = (getSystemService(Context.POWER_SERVICE) as PowerManager).run {
                    newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WakelockTag123").apply {
                        acquire()
                    }
                }
    }


        override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
            val serviceAction = intent?.action
            LogUtils.logD("OnStartCommand(). Action=$serviceAction")
            if (Constants.INTENT.ACTION_STOP_SERVICE == serviceAction) {
                LogUtils.logD("Stopping data capture service")
                stopForeground(true)
                stopSelf()
            } else if (Constants.INTENT.ACTION_START_SERVICE == serviceAction && !isServiceStarted) {
                LogUtils.logD("Starting data capture service")
                isServiceStarted = true
                // Here showing notification using a utility method (startForeground(id, notification))
                createNotification(this)
                // Doing some stuff here
                ----------------------
                //
            }
            return START_STICKY
        }

        override fun onDestroy() {
            super.onDestroy()
            if (isServiceStarted) {
                LogUtils.logD("onDestroy of DataCaptureService method is invoked")
                // Doing some stuff here
                ----------------------
                //
                isServiceStarted = false
                if (wakeLock.isHeld) {
                    wakeLock.release()
                }
            }
        }

        override fun onTaskRemoved(rootIntent: Intent?) {
            LogUtils.logD("onTaskRemoved of DataCaptureService method is invoked")
            ensureServiceStaysRunning()
            super.onTaskRemoved(rootIntent)
        }

        private fun ensureServiceStaysRunning() {
            val restartAlarmInterval = 60 * 1000
            val resetAlarmTimer = 30 * 1000L
            // From this broadcast I am restarting the service
            val restartIntent = Intent(this, ServiceRestartBroadcast::class.java)
            restartIntent.action = "RestartedViaAlarm"
            restartIntent.flags = Intent.FLAG_RECEIVER_FOREGROUND
            val alarmMgr = getSystemService(Context.ALARM_SERVICE) as AlarmManager
            val restartServiceHandler = @SuppressLint("HandlerLeak")
            object : Handler() {
                override fun handleMessage(msg: Message) {
                    val pendingIntent = PendingIntent.getBroadcast(applicationContext, 87, restartIntent, PendingIntent.FLAG_CANCEL_CURRENT)
                    val timer = System.currentTimeMillis() + restartAlarmInterval
                    val sdkInt = Build.VERSION.SDK_INT
                    if (sdkInt < Build.VERSION_CODES.KITKAT)
                        alarmMgr.set(AlarmManager.RTC_WAKEUP, timer, pendingIntent)
                    else if (Build.VERSION_CODES.KITKAT <= sdkInt && sdkInt < Build.VERSION_CODES.M)
                        alarmMgr.setExact(AlarmManager.RTC_WAKEUP, timer, pendingIntent)
                    else if (sdkInt >= Build.VERSION_CODES.M) {
                        alarmMgr.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, timer, pendingIntent)
                    }
                    sendEmptyMessageDelayed(0, resetAlarmTimer)
                    stopSelf()
                }
            }
            restartServiceHandler.sendEmptyMessageDelayed(0, 0)
        }

    }

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

Ответы [ 5 ]

0 голосов
/ 21 мая 2019

в oneplus 6t, запустите эту команду adb

, установив put system1003 *

предотвратить убийство com.topjohnwu.magisk и com.mycompany.MyAndroidApp

0 голосов
/ 19 декабря 2018

Я потратил несколько часов на решение этой проблемы.Телефон Xiaomi, Oreo.У меня есть решение, 2 шага:

  1. Xiaomi требует дополнительного разрешения: Настройки-> Разрешения-> Автоматический запуск.Существует список приложений, которые разрешено запускать автоматически.BOOT_COMPLETED и START_STICKY недостаточно.Facebook, Outlook, Skype + мое приложение указано здесь.Я не знаю, как программно попросить пользователя предоставить это разрешение.

  2. Служба воссоздается, но НЕ перезапускается, даже если вы возвращаете START_STICKY.После того, как вы закроете приложение (удалите из запущенных приложений), снова вызывается onCreate, но НЕ onStartCommand.Попробуйте Log.d (), чтобы увидеть это.Я переместил всю логику в onCreate EXCEPT, создав уведомление, вызвав startForeground () и вернув START_STICKY.Это должно оставаться в onStartCommand ().

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

Теперь мойслужба продолжает работать или воссоздается со 100% успехом в течение нескольких секунд.

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

Я столкнулся с той же проблемой в моем OnePlus3 для моего приложения.Затем я заметил эти строки в logcat, каждый раз, когда мое приложение и служба Foreground были убиты:

10-12 18:30:40.644  1439  1519 I OHPD    : [BgDetect]force stop com.mycompany.MyAndroidApp (uid 10905) level 0
10-12 18:30:40.645  1439  1519 I ActivityManager: Force stopping com.mycompany.MyAndroidApp appid=10905 user=0: from pid 1439
10-12 18:30:40.645  1439  1519 I ActivityManager: Killing 23139:com.mycompany.MyAndroidApp/u0a905 (adj 200): stop com.mycompany.MyAndroidApp
10-12 18:30:40.647  1439  1519 W ActivityManager: Scheduling restart of crashed service com.mycompany.MyAndroidApp/md55852635cfc9dced970aa39ae09e74ead.MyForegroundService in 1000ms
10-12 18:30:40.651  1439  1519 I ActivityManager:   Force finishing activity ActivityRecord{a5c8d39 u0 com.mycompany.MyAndroidApp/md55852635cfc9dced970aa39ae09e74ead.MainActivity t3108}
10-12 18:30:40.655  1439  1519 I ActivityManager:   Force stopping service ServiceRecord{6052f94 u0 com.mycompany.MyAndroidApp/md55852635cfc9dced970aa39ae09e74ead.MyForegroundService}
10-12 18:30:40.660  1439  1519 I OHPD    : [BgDetect]chkExcessCpu level: 1 doKills: true critical false uptime: 300328
10-12 18:30:40.710  1439  8213 I WindowManager: WIN DEATH: Window{c381342 u0 com.mycompany.MyAndroidApp/md55852635cfc9dced970aa39ae09e74ead.MainActivity}

Затем поиск в Интернете по ключевым словам «OHPD: [BgDetect] chkExcessCpu level: 1 doKills: true» забирал меняна этот SO-ответ:

Предотвращение уничтожения фоновой службы из-за «обнаружения чрезмерного процессора при разветвленном процессе»

Как предлагается в этом ответе и проблеме GitHub, Блокировка/ Закрепление моего приложения не позволило Oxygen OS убить мое приложение (MainActivity и Forground Service).

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

Я проанализировал проблему на OnePlus, так как я нахожусь в той же ситуации, что и вы.Как я вижу в настоящее время, нет никакого решения.OnePlus явно следует плохой практике.

Поскольку они не выпустили исходный код, который убивает процессы таким образом, я загрузил ПЗУ OnePlus (я выбираю OnePlus 5T 5.1.5), распакуйте его и найдите.класс, который делает это (OnePlusHighPowerDetector.class в services.vdex), декомпилирует его и пытается выяснить, что происходит.

Вы можете найти версию этого класса здесь (это не я, и, возможно,это не та версия, которую я использовал): https://github.com/joshuous/oneplus_blobs_decompiled/blob/master/com/android/server/am/OnePlusHighPowerDetector.java

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

  • OnePlus убивает фоновые процессы (кажется, что не имеет значения, имеет ли он приоритетный сервис или нет) без пощады.Почти все из них.Неважно, насколько мало ресурсов процессора используется.Мое приложение использует менее 1% и уничтожается.
  • Если приложение добавлено в список последних приложений (определяется списком com_oneplus_systemui_recent_task_lockd_list), оно не будет уничтожено.Таким образом, пользователь может сохранить приложение, закрепив его.Но это неудобно для них.
  • Oneplus предоставляет список процессов, которые они не убивают.Этот список находится в oneplus-framework-res.apk/res/values/array.xml, с ключом string-array name="backgroundprocess_detection_app_whitelist".Этот список в основном содержит приложения для карт и фитнеса 1 .
  • Возможно, есть и другие факторы, которые могут спасти процесс, который я убил, я больше не анализировал проблему.Если у вас есть время, посмотрите OnePlusHighPowerDetector.java.

Вот шаги, необходимые для декомпиляции файла .vdex:

  • use VdexExtractor для создания .dex из .vdex (возможно, вам нужно будет использовать опцию --ignore-crc-error)
  • использовать JADX для декомпиляции .dex (в настоящее время этолучший декомпилятор на мой взгляд), или используйте dex2jar для создания .jar из .dex, и используйте любой декомпилятор для декомпиляции .jar

1 Rant: показывает, насколько плоха текущая ситуация.OnePlus, это действительно решение?Вы выбрали 10-15 приложений, которые могут работать в фоновом режиме, и вас не волнуют все остальные?Как создать новое приложение для фитнеса / карты / музыкального проигрывателя, которое безопасно работает на вашем устройстве?

0 голосов
/ 20 сентября 2018

используйте startForeground(id, notification) метод внутри вашего сервиса.

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

Кстати, вы можете использовать WakeLock .

 PowerManager powerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
 PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PARTIAL_WAKE_LOCK, 
 TAG_FOR_DEBUG);
 wakeLock.acquire()

Но прочитайте о WakeLock перед его использованием.И не забудьте отключить его, когда ваша работа будет завершена.

Вы можете проверить текущие включенные пробуждения, используя команду adb shell dumpsys power в Terminal

...