Browse Source

simplify notification background task

B. Petersen 4 năm trước cách đây
mục cha
commit
912e4cfaed
1 tập tin đã thay đổi với 45 bổ sung57 xóa
  1. 45 57
      deltachat-ios/Helper/NotificationManager.swift

+ 45 - 57
deltachat-ios/Helper/NotificationManager.swift

@@ -7,7 +7,6 @@ public class NotificationManager {
     
     var incomingMsgObserver: NSObjectProtocol?
     var msgsNoticedObserver: NSObjectProtocol?
-    private var notificationBackgroundTasks = [Int: UIBackgroundTaskIdentifier]()
 
 
     init() {
@@ -39,31 +38,20 @@ public class NotificationManager {
             NotificationManager.updateApplicationIconBadge(reset: false)
         }
     }
-    
-    private func unregisterNotificationBackgroundTask(msgId: Int) {
-        let backgroundTask = notificationBackgroundTasks[msgId]
-        if let backgroundTask = backgroundTask, backgroundTask != .invalid {
-            UIApplication.shared.endBackgroundTask(backgroundTask)
-            notificationBackgroundTasks.removeValue(forKey: msgId)
-            logger.info("⬅️ notification background task ended and removed: \(msgId)")
-        }
-    }
-    
-    private func registerNotificationBackgroundTask(msgId: Int) {
-        logger.info("⬅️ notification notification background task: \(msgId)")
-        let backgroundTask = UIApplication.shared.beginBackgroundTask { [weak self] in
-            logger.info("⬅️ notification background expirationHandler called")
-            self?.unregisterNotificationBackgroundTask(msgId: msgId)
-        }
-        notificationBackgroundTasks[msgId] = backgroundTask
-    }
 
     private func initIncomingMsgsObserver() {
         incomingMsgObserver = NotificationCenter.default.addObserver(
             forName: dcNotificationIncoming,
             object: nil, queue: OperationQueue.main
         ) { notification in
-            DispatchQueue.global(qos: .background).async { [weak self] in
+            // make sure to balance each call to `beginBackgroundTask` with `endBackgroundTask`
+            let backgroundTask = UIApplication.shared.beginBackgroundTask {
+                // we cannot easily stop the task,
+                // however, this handler should not be called as adding the notification should not take 30 seconds.
+                logger.info("notification background task will end soon")
+            }
+
+            DispatchQueue.global(qos: .background).async {
                 if let ui = notification.userInfo,
                    let chatId = ui["chat_id"] as? Int,
                    let messageId = ui["message_id"] as? Int,
@@ -72,47 +60,47 @@ public class NotificationManager {
                     NotificationManager.updateApplicationIconBadge(reset: false)
 
                     let chat = DcContext.shared.getChat(chatId: chatId)
-                    if chat.isMuted {
-                        return
-                    }
-                    
-                    self?.registerNotificationBackgroundTask(msgId: messageId)
-                    let content = UNMutableNotificationContent()
-                    let msg = DcMsg(id: messageId)
-                    content.title = chat.isGroup ? chat.name : msg.getSenderName(msg.fromContact)
-                    content.body =  msg.summary(chars: 80) ?? ""
-                    content.subtitle = chat.isGroup ?  msg.getSenderName(msg.fromContact) : ""
-                    content.userInfo = ui
-                    content.sound = .default
-
-                    if msg.type == DC_MSG_IMAGE || msg.type == DC_MSG_GIF,
-                       let url = msg.fileURL {
-                        do {
-                            // make a copy of the file first since UNNotificationAttachment will move attached files into the attachment data store
-                            // so that they can be accessed by all of the appropriate processes
-                            let tempUrl = url.deletingLastPathComponent()
-                                .appendingPathComponent("notification_tmp")
-                                .appendingPathExtension(url.pathExtension)
-                            try FileManager.default.copyItem(at: url, to: tempUrl)
-                            if let attachment = try? UNNotificationAttachment(identifier: Constants.notificationIdentifier, url: tempUrl, options: nil) {
-                                content.attachments = [attachment]
+                    if !chat.isMuted {
+                        let content = UNMutableNotificationContent()
+                        let msg = DcMsg(id: messageId)
+                        content.title = chat.isGroup ? chat.name : msg.getSenderName(msg.fromContact)
+                        content.body =  msg.summary(chars: 80) ?? ""
+                        content.subtitle = chat.isGroup ?  msg.getSenderName(msg.fromContact) : ""
+                        content.userInfo = ui
+                        content.sound = .default
+
+                        if msg.type == DC_MSG_IMAGE || msg.type == DC_MSG_GIF,
+                           let url = msg.fileURL {
+                            do {
+                                // make a copy of the file first since UNNotificationAttachment will move attached files into the attachment data store
+                                // so that they can be accessed by all of the appropriate processes
+                                let tempUrl = url.deletingLastPathComponent()
+                                    .appendingPathComponent("notification_tmp")
+                                    .appendingPathExtension(url.pathExtension)
+                                try FileManager.default.copyItem(at: url, to: tempUrl)
+                                if let attachment = try? UNNotificationAttachment(identifier: Constants.notificationIdentifier, url: tempUrl, options: nil) {
+                                    content.attachments = [attachment]
+                                }
+                            } catch let error {
+                                logger.error("Failed to copy file \(url) for notification preview generation: \(error)")
                             }
-                        } catch let error {
-                            logger.error("Failed to copy file \(url) for notification preview generation: \(error)")
                         }
+                        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.1, repeats: false)
+                        let accountEmail = DcContact(id: Int(DC_CONTACT_ID_SELF)).email
+                        if #available(iOS 12.0, *) {
+                            content.threadIdentifier = "\(accountEmail)\(chatId)"
+                        }
+                        let request = UNNotificationRequest(identifier: "\(Constants.notificationIdentifier).\(accountEmail).\(chatId).\(msg.messageId)",
+                                                            content: content,
+                                                            trigger: trigger)
+                        UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
+                        logger.info("notifications: added \(content.title) \(content.body) \(content.userInfo)")
                     }
-                    let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.1, repeats: false)
-                    let accountEmail = DcContact(id: Int(DC_CONTACT_ID_SELF)).email
-                    if #available(iOS 12.0, *) {
-                        content.threadIdentifier = "\(accountEmail)\(chatId)"
-                    }
-                    let request = UNNotificationRequest(identifier: "\(Constants.notificationIdentifier).\(accountEmail).\(chatId).\(msg.messageId)",
-                                                        content: content,
-                                                        trigger: trigger)
-                    UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
-                    logger.info("notifications: added \(content.title) \(content.body) \(content.userInfo)")
-                    self?.unregisterNotificationBackgroundTask(msgId: messageId)
                 }
+
+                // this line should always be reached
+                // and balances the call to `beginBackgroundTask` above.
+                UIApplication.shared.endBackgroundTask(backgroundTask)
             }
         }
     }