【问题标题】:Foreground service killed on Oreo前台服务在奥利奥上被杀死
【发布时间】:2019-05-30 23:50:27
【问题描述】:

我正在为我的前台服务而苦苦挣扎。在我的设备(Redmi 5 Plus,Android 8.1.0)上,服务通知不再可见 应用程序已从最近的应用程序中删除。在其他设备(Android 5.0.1、Android 7.0)和模拟器(android 8.1 - api 27)上,当从最近的应用中删除应用时,通知仍然可见。

在主要活动中,我使用ContextCompat.startForegroundService(this, intent) 来启动我的服务。

前台服务代码如下:

package com.ngallazzi.bluetoothtests.services

import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.app.*
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.IBinder
import android.support.v4.app.NotificationCompat
import android.support.v4.app.NotificationCompat.PRIORITY_LOW
import android.util.Log
import com.ngallazzi.blemanager.managers.DeviceScanningListener
import com.ngallazzi.blemanager.managers.InRangeDetectionManager
import com.ngallazzi.bluetoothtests.MainActivity
import com.polidea.rxandroidble2.RxBleDevice


/**
 * BluetoothTests
 * Created by Nicola on 12/17/2018.
 * Copyright © 2018 Zehus. All rights reserved.
 */

class DeviceDetectionService : Service() {

    private lateinit var detectionManager: InRangeDetectionManager

    override fun onBind(intent: Intent): IBinder? {
        // We don't provide binding, so return null
        return null
    }

    override fun onCreate() {
        super.onCreate()
        detectionManager = InRangeDetectionManager(this)
    }

    @SuppressLint("MissingPermission")
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        if (intent != null) {
            val action = intent.action

            when (action) {
                ACTION_START_FOREGROUND_SERVICE -> {
                    startForegroundService()
                    detectionManager.startDeviceScanning(object : DeviceScanningListener {
                        @SuppressLint("CheckResult")
                        override fun onDeviceFound(device: RxBleDevice) {
                            device.establishConnection(false).subscribe({
                                Log.v(TAG, "Connected")
                                displayNotification(getNotification("Connected with: {${device.name}}"))
                            }, {
                                displayNotification(getNotification("An error occurred: {$it.message!!}"))
                            })
                        }

                        override fun onError(message: String?) {
                            displayNotification(getNotification("An error occurred: {$message}"))
                        }

                    })
                }
                ACTION_STOP_FOREGROUND_SERVICE -> {
                    stopForegroundService()
                }
            }

        }
        return START_NOT_STICKY
    }

    @SuppressLint("MissingPermission")
    private fun startForegroundService() {
        startForeground(NOTIFICATION_ID, getNotification(SEARCHING_DEVICES_MESSAGE))
        Log.v(TAG, "Device detection service started")
    }

    private fun getNotification(message: String): Notification {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
            createChannel()

        val mBuilder = NotificationCompat.Builder(this, CHANNEL_NAME).apply {
            setSmallIcon(android.R.drawable.ic_menu_mylocation)
            setContentTitle(message)
            setContentIntent(getMainActivityPendingIntent())
        }

        return mBuilder
            .setPriority(PRIORITY_LOW)
            .setCategory(Notification.CATEGORY_SERVICE)
            .build()
    }

    private fun displayNotification(notification: Notification) {
        val mNotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        mNotificationManager.notify(NOTIFICATION_ID, notification)
    }

    private fun getMainActivityPendingIntent(): PendingIntent {
        // Create an Intent for the activity you want to start
        val intent = Intent(this, MainActivity::class.java)
        // Create the TaskStackBuilder
        val pendingIntent = PendingIntent.getActivity(
            this, 0,
            intent, PendingIntent.FLAG_UPDATE_CURRENT
        );
        return pendingIntent!!
    }

    @TargetApi(26)
    @Synchronized
    private fun createChannel() {
        val mNotificationManager = this.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        val importance = NotificationManager.IMPORTANCE_DEFAULT

        val mChannel = NotificationChannel(CHANNEL_NAME, SEARCHING_DEVICES_MESSAGE, importance)

        mNotificationManager.createNotificationChannel(mChannel)
    }

    private fun stopForegroundService() {
        Log.d(TAG, "Stop foreground service.")

        // Stop foreground service and remove the notification.
        stopForeground(true)

        // Stop the foreground service.
        stopSelf()
    }


    override fun onDestroy() {
        super.onDestroy()

    }

    companion object {
        private val TAG = DeviceDetectionService::class.java.simpleName

        const val NOTIFICATION_ID = 1
        const val ACTION_START_FOREGROUND_SERVICE = "start_service"
        const val ACTION_STOP_FOREGROUND_SERVICE = "stop_service"
        const val CHANNEL_NAME = "DEVICE_DETECTION_SERVICE"
        const val SEARCHING_DEVICES_MESSAGE = "Searching in range device"
    }
}

这是我的清单文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.ngallazzi.bluetoothtests">

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
            android:allowBackup="true"
            android:name=".App"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
        <activity android:name=".MainActivity" android:launchMode="singleInstance">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <service android:name=".services.DeviceDetectionService" android:enabled="true"/>

        <receiver android:name=".BootCompletedReceiver" android:enabled="true" android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
                <action android:name="android.intent.action.REBOOT"/>
                <action android:name="android.intent.action.QUICKBOOT_POWERON"/>
            </intent-filter>
        </receiver>

    </application>

</manifest>

我错过了什么?是否与后台执行限制有关?

【问题讨论】:

  • 你读过this吗?实际上我没有尝试但阅读docs 似乎您还需要在调用后的 5 秒内调用您的服务 startForeground()。看起来你不叫它,但我在一个“金发女郎”(啤酒)面前,我可能错过了一些东西。
  • @shadowsheep 谢谢我读了它,但我在 startForegroundService() 方法中调用 startForeground(),只要我从启动活动中获得 ACTION_START_FOREGROUND_SERVICE 命令。享受您的啤酒,感谢您的贡献:)
  • 啊哈!现在我看到了^^',我在我的笔记本电脑前。对我来说看起来不错。由于您的问题不太清楚,您认为问题是特定于 API 级别(即 Oreo)还是设备?我想知道在 API 级别 >= 26 的另一台设备上,您的代码是否会按预期工作。我可以建议您在没有所有 BLE 部分的情况下尝试您的服务。我刚刚在运行 API 级别 27 的模拟器上进行了尝试,如果我终止该应用程序,该服务仍然存在。顺便说一句,当你杀死你的应用程序时,为什么你想让前台服务仍在运行?随着所有新限制的到来,维护起来会很痛苦。
  • @shadowsheep 感谢您关注我 :)。可能是 android 版本 8.1.0 特有的问题,并且在我测试的其他设备上没有发生。我已经尝试过没有 BLE 部分的服务,同样的行为 :(。前台服务的目的是扫描特定的 ble 设备并在设备进入我的手机范围内时自动连接到它
  • “杀死应用程序”是什么意思。对于 Android 开发人员来说,没有像“杀死应用程序”这样的事情 - 准确地说。

标签: android android-8.0-oreo foreground-service


【解决方案1】:

试试这个

第 1 步)在您的服务类标签中添加此标签 android:process android:process="classname" 清单文件

然后在服务类中这样做

第 2 步)在服务类中覆盖 onTaskRemoved()

使用报警管理器重启服务

步骤 3) 要求用户启用 autorun persmission 已自定义操作系统

如果用户启用它,那么您的服务将在应用被杀死后运行。

Link for autoenable permission code

注意:- 复制这段代码并粘贴,Kotlin 转换器会自动转换

【讨论】:

  • 这对我来说似乎有点矫枉过正,但我​​会试一试:)
  • 不幸的是没有任何变化:(
  • 允许自动运行权限后测试了吗?
  • 是的,我没有使用您的库,但我在手机上的应用设置中设置了权限
  • 更新了清单,我也尝试过 android:name=".services.DeviceDetectionService" android:process=":services.DeviceDetectionService"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多