推送通知后台被用户杀死

Posted

技术标签:

【中文标题】推送通知后台被用户杀死【英文标题】:Push notification background killed by the user 【发布时间】:2019-12-11 04:24:12 【问题描述】:

当应用程序在后台被用户杀死时正在接收推送,当用户点击推送通知时,它会打开应用程序并且它不会崩溃但会立即关闭。

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) 
        // If you are receiving a notification message while your app is in the background,
        // this callback will not be fired till the user taps on the notification launching the application.

        // With swizzling disabled you must let Messaging know about the message, for Analytics
        Messaging.messaging().appDidReceiveMessage(userInfo)

        // Print message ID.
        print("The userInfo is: \(userInfo)")

        completionHandler(UIBackgroundFetchResult.newData)
    

之前的方法甚至没有被调用,或者可能是,但我不知道如何调试它,因为应用程序没有运行。

这是我通过服务器发送的通知对象:

apns: 
                payload: 
                    aps: 
                        alert: 
                            title: messageObject.authorName,
                            body: messageObject.content,
                        ,
                        sound: "notification.wav",
                        category: "ChatViewController"
                    
                
            

这就是通过服务器发送的内容。当应用程序在后台并且没有被杀死,或者当应用程序在前台时,通知会起作用。

【问题讨论】:

当应用程序被杀死并且您单击通知时,您需要在 appDelegate 方法 didFinishLaunchingWithOptions 中处理该场景。 你怎么能确定应用程序没有崩溃而不是关闭? 我发现应用程序确实被关闭了,但是UNNotificationResponse 为零。这怎么可能在后台这个对象不是 nil,但是当应用程序被杀死时却不是? 【参考方案1】:

我认为当用户在您的应用程序被终止或在后台或前台单击通知时,将执行以下方法。而且你必须一一测试。

首先检查您是否能够在单击通知时在应用程序运行时立即看到弹出窗口。只需复制,将此代码粘贴到您的 AppDelegate 类中并注释您的 didReceiveRemoteNotification 方法,然后检查您的应用程序是否崩溃。

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) 
    guard let object = response.notification.request.content.userInfo as? [String : AnyObject] else 
     return 
  

    self.normalPopup()
 

 /// Alert Popup, if user not exist in our database.
func normalPopup() 

    let alert = UIAlertController(title: "Test", message: "Show pop up window.", preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "OK", style: .default, handler:  (action) in
    ))
    self.window?.rootViewController?.present(alert, animated: true)

如果显示弹出窗口,则注释 normalPopup 函数并将该函数替换为以下代码。然后检查您的应用程序是否在应用程序终止时崩溃。

    Messaging.messaging().appDidReceiveMessage(userInfo)

如果您仍然面临同样的问题,请告诉我。

【讨论】:

我发现应用程序确实被关闭了,但是UNNotificationResponse 为零。这怎么可能在后台这个对象不是 nil,但是当应用程序被杀死时却不是? 首先我并不清楚你的意思是什么。到目前为止,我从您的角度理解。当您当时单击任何通知时,操作系统将激活您的应用程序,并且当您的通知委托方法触发时,UNNotificationResponse 不为零。您将在此委托方法中获取有效负载对象。【参考方案2】:

如果您首先使用 firebase,您应该在 application(_ application:, didFinishLaunchingWithOptions:) 上定义它,如下所示:

  
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool 
        
        if #available(ios 10.0, *) 
          // For iOS 10 display notification (sent via APNS)
          UNUserNotificationCenter.current().delegate = self

          let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
          UNUserNotificationCenter.current().requestAuthorization(
            options: authOptions,
            completionHandler: _, _ in )
         else 
          let settings: UIUserNotificationSettings =
          UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
          application.registerUserNotificationSettings(settings)
        
        
        application.registerForRemoteNotifications()

        Messaging.messaging().delegate = self
        
        FirebaseApp.configure()
        return true
    
        

您还可以在应用程序运行时处理通知,使用此功能:


func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) 
        
        if let messageID = userInfo["gcm.message_id"] 
          print("Message ID: \(messageID)")
        
        // Print full message.
        print(userInfo)
       
        completionHandler(UIBackgroundFetchResult.newData)
    

 func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) 
        
        if let messageID = userInfo["gcm.message_id"] 
          print("Message ID: \(messageID)")
        

        // Print full message.
        print(userInfo)
        
    

您应该使用此方法将新令牌设置为消息传递:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) 

        Messaging.messaging().apnsToken = deviceToken
        let token = deviceToken.map  String(format: "%02.2hhx", $0).joined()
        print(token)
        
    

最后,您可以使用以下扩展名处理通知


// [START ios_10_message_handling]
@available(iOS 10, *)
extension AppDelegate: UNUserNotificationCenterDelegate 

  // Receive displayed notifications for iOS 10 devices.
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) 
        let userInfo = notification.request.content.userInfo
        
        if let messageID = userInfo["gcm.message_id"] 
            print("Message ID: \(messageID)")
        

    //*************************
    // Handle push notification message automatically when app is running 
    //*************************
    print(userInfo)

    // Change this to your preferred presentation option
    completionHandler([[.alert, .sound]])
  

  func userNotificationCenter(_ center: UNUserNotificationCenter,
                              didReceive response: UNNotificationResponse,
                              withCompletionHandler completionHandler: @escaping () -> Void) 
    let userInfo = response.notification.request.content.userInfo
    // Print message ID.
    if let messageID = userInfo["gcm.message_id"] 
      print("Message ID: \(messageID)")
    

    //*************************
    // Handle push notification message after click on it
    //*************************

    print(userInfo)

    completionHandler()
  


【讨论】:

以上是关于推送通知后台被用户杀死的主要内容,如果未能解决你的问题,请参考以下文章

如果应用程序被杀死/运行,ios显示/隐藏通知

在应用程序未运行时处理推送通知(应用程序被杀死)

当应用程序被杀死时,iOS 没有收到推送通知

使用firebase发送静默推送通知,以便在应用程序被杀死时唤醒它

当应用程序被杀死Android时无法接收解析推送通知

应用程序被杀死/关闭/未打开时的 IOS 推送通知操作