【发布时间】: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>
我错过了什么?是否与后台执行限制有关?
【问题讨论】:
-
@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