Two or more Foreground Notification with Progress is replacing each other while updating its progress

前端 未结 4 1099
北恋
北恋 2021-01-22 04:15

I have a service that will run a upload task in foreground then showing a progress in the notification. Since a user may upload multiple times with different id request then the

4条回答
  •  青春惊慌失措
    2021-01-22 04:45

    Before you call startForeground, you need to call ServiceCompat.stopForeground(service, ServiceCompat.STOP_FOREGROUND_DETACH) to keep the old notification(s).

    The following is a utility class that you can use in the foreground service to manage the notifications:

    class ForegroundNotifications(
        private val context: Context,
        private val foregroundServiceHelper: ForegroundServiceHelper,
        private val notificationService: NotificationService
    ) {
    
        var activeNotificationId: Int? = null
            private set
    
        val notificationIds: Set
            get() = entries.keys
    
        val isEmpty: Boolean
            get() = entries.isEmpty()
    
        private val entries: LinkedHashMap = LinkedHashMap()
    
        fun notifyAndDetachPrevious(notificationId: Int, notification: Notification) {
            synchronized(this) {
                foregroundServiceHelper.startForegroundAndDetachPreviousNotification(
                    notificationId,
                    notification
                )
    
                entries[notificationId] = notification
                activeNotificationId = notificationId
            }
        }
    
        fun cancel(notificationId: Int) {
            synchronized(this) {
                if (notificationId == activeNotificationId) {
                    val newActiveNotificationId = entries.keys.findLast { it != activeNotificationId }
                    val notification = entries[newActiveNotificationId]
    
                    if (newActiveNotificationId != null && notification != null) {
                        notifyAndDetachPrevious(newActiveNotificationId, notification)
                    }
                }
    
                entries.remove(notificationId)
    
                if (isEmpty) {
                    foregroundServiceHelper.stopForeground()
                } else {
                    notificationService.cancel(context, id = notificationId)
                }
            }
        }
    
    }
    
    interface NotificationService {
    
        fun createDefaultChannel(context: Context)
    
        fun notify(context: Context, tag: String? = null, id: Int, notification: Notification)
    
        fun cancel(context: Context, tag: String? = null, id: Int)
    
    }
    
    interface ForegroundServiceHelper {
    
        fun startForegroundAndDetachPreviousNotification(
            notificationId: Int,
            notification: Notification
        )
    
        fun stopForeground()
    
    }
    
    class ForegroundServiceHelperImpl(
        private val service: Service
    ) : ForegroundServiceHelper {
    
        override fun startForegroundAndDetachPreviousNotification(
            notificationId: Int,
            notification: Notification
        ) {
            ServiceCompat.stopForeground(service, ServiceCompat.STOP_FOREGROUND_DETACH)
            service.startForeground(notificationId, notification)
        }
    
        override fun stopForeground() {
            ServiceCompat.stopForeground(service, ServiceCompat.STOP_FOREGROUND_REMOVE)
        }
    
    }
    

提交回复
热议问题