Fix NotificationService implementation

- Fix #6385. (Maybe the reason is, the call to stopForeground() with STOP_FOREGROUND_DETACH ensures the notification is shown so it reposts the notification?)
- Use FOREGROUND_SERVICE_IMMEDIATE on Android 12+ to make sure the downloading notification always shows immediately
This commit is contained in:
canyie 2022-12-31 23:52:23 +08:00 committed by John Wu
parent 78a444d601
commit cb39514705
2 changed files with 27 additions and 11 deletions

View File

@ -20,6 +20,8 @@ open class NotificationService : BaseService() {
protected val service get() = ServiceLocator.networkService
private var attachedNotificationId = 0
override fun onTaskRemoved(rootIntent: Intent?) {
super.onTaskRemoved(rootIntent)
notifications.forEach { Notifications.mgr.cancel(it.key) }
@ -74,32 +76,44 @@ open class NotificationService : BaseService() {
subject.pendingIntent(this)?.let { intent -> it.setContentIntent(intent) }
}
private fun updateForegroundState() {
private fun attachNotification(id: Int, notification: Notification) {
attachedNotificationId = id
startForeground(id, notification)
}
private fun maybeDetachNotification(id: Int) : Boolean {
if (attachedNotificationId != id) return false
if (hasNotifications) {
val (id, notification) = notifications.entries.first()
startForeground(id, notification.build())
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
stopForeground(STOP_FOREGROUND_DETACH)
val (anotherId, notification) = notifications.entries.first()
// Attaching a new notification will remove the current showing one
attachNotification(anotherId, notification.build())
return true
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
stopForeground(STOP_FOREGROUND_REMOVE)
} else {
@Suppress("DEPRECATION")
stopForeground(false)
stopForeground(true)
}
attachedNotificationId = 0
return true
}
protected fun notifyUpdate(id: Int, editor: (Notification.Builder) -> Unit = {}) {
fun create() = Notifications.startProgress("")
val wasEmpty = !hasNotifications
val notification = notifications.getOrPut(id, ::create).also(editor)
val notification = notifications.getOrPut(id, ::create).also(editor).build()
if (wasEmpty)
updateForegroundState()
attachNotification(id, notification)
else
Notifications.mgr.notify(id, notification.build())
Notifications.mgr.notify(id, notification)
}
protected fun notifyRemove(id: Int): Notification.Builder? {
val n = notifications.remove(id)?.also { updateForegroundState() }
Notifications.mgr.cancel(id)
val n = notifications.remove(id)
if (n == null || !maybeDetachNotification(id))
Notifications.mgr.cancel(id)
return n
}

View File

@ -96,6 +96,8 @@ object Notifications {
.setContentTitle(title)
.setProgress(0, 0, true)
.setOngoing(true)
if (SDK_INT >= Build.VERSION_CODES.S)
builder.setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE)
return builder
}