静默推送不触发代码执行

Posted

技术标签:

【中文标题】静默推送不触发代码执行【英文标题】:Silent push not triggering the code execution 【发布时间】:2020-03-28 09:59:21 【问题描述】:

我每 30 分钟发送一次静默推送通知,我想在静默通知到达设备时执行代码。但经过多次尝试,我无法得到结果。当我在我的设备上测试它(使用 Xcode 的版本)时,一切正常,在将其上传到 TestFlight 并从 TestFlight 下载版本后,我无法从后台唤醒应用程序或将其从终止状态唤醒。只需在启动应用程序或应用程序进入前台后执行此代码。

根据Apple documentation,我应该能够唤醒应用程序并执行 30 秒的代码。 我确认已成功发送无提示通知。我遗漏了什么?

AppDelegate.swift

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                 fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) 
    if let messageID = userInfo[gcmMessageIDKey] 
        print("Message ID: \(messageID)")
    

    guard (userInfo["aps"] as? [String?: Any]) != nil else 
        Analytics.logEvent("fetch_failed", parameters: nil)
        completionHandler(.failed)
        return
    

    let login = UserDefaults.standard.value(forKey: "username") as? String
    let password = UserDefaults.standard.value(forKey: "password") as? String

    if login != nil && password != nil 
        let session = URLSession.shared
        let url = URL(string: "https://example.com")!
        let body_values = Data(("credentials...").utf8)
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.setValue("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/77.0.3865.120 Safari/537.36", forHTTPHeaderField: "User-Agent")
        request.httpBody = body_values

        let loadDataTask = session.dataTask(with: request)  data, response, error in
            if let httpResponse = response as? HTTPURLResponse 
                print(httpResponse.statusCode)
                if httpResponse.statusCode == 200 
                    if let data = data, let dataString = String(data: data, encoding: .utf8) 
                        let htmlparser: HTMLParser = HTMLParser()
                        let numberOfEmails = htmlparser.getXPathvalue(xPath: "/html/body/div[1]/div[3]/div[3]/a[1]", fromHtml: dataString)
                        self.setNotification(title: "New emails!", body: "Count of new emails: \(numberOfEmails)")
                        completionHandler(.newData)
                    
                    else 
                        completionHandler(.failed)
                    
                
                else 
                    completionHandler(.failed)
                
            
            else 
                completionHandler(.failed)
            
        
        loadDataTask.resume()
    
    else 
        completionHandler(.failed)
    

PushNotification.js

var message = 
  notification: 
  ,
  apns: 
     headers: 
        'apns-priority' : '5',
        'apns-push-type' : 'background'
     ,
     payload: 
         aps: 
            'content-available' : 1
         
     
   ,
   topic: topic
;

【问题讨论】:

除了 Caio 的观察之外,您的完成处理程序逻辑不正确。假设网络请求成功:您将使用.newData.noData.failed 调用完成处理程序三次!其次,如果网络请求由于某种原因失败,您根本不会调用完成处理程序。第三,如果登录名或密码为 nil,您也不会调用完成处理程序。最重要的是,确保每条执行路径都精确地调用一次完成处理程序。 在测试这类东西时,我喜欢unified logging,因此我可以从我的 macOS 控制台查看来自我的 ios 应用程序的日志消息,而无需通过 Xcode 调试器运行它,这可以改变应用程序的生命周期。有关演示,请参阅 Unified Logging and Activity Tracing 视频。 如果您原谅不相关的观察: 1. 确保在您的 URL 中包含“https://”方案。 2. 对于未编码的请求添加密码,我会很谨慎。如果它有一个像& 这样的保留字符呢?我建议 percent-encoding 使用您的 x-www-form-urlencoded 请求中的值。 嗨@Rob,感谢您的评论。我在这里更新了代码,你可以看看。但是,即使我到处都有完成处理程序,启用了后台获取和远程通知,我也只能在我的 Xcode 版本的设备上执行静默推送,Testflight 版本不起作用......我完全迷失了。 【参考方案1】:

在this apple forum discussion! 中讨论了您必须注意的两个主要事项。第一个是app不能被终止,否则不会启动app,必须是前台或者后台。另一个是你需要在Info.plist中启用后台模式才能让它工作。除了在某些情况下系统不会只刷新您的应用程序之外,您最大的保证是只有当用户单击您的应用程序收到的通知时,否则由于某些隐私问题,它可能无法正常工作。

【讨论】:

我已在功能中启用远程通知。我应该启用后台获取还是后台处理? 是的,你应该尝试一下,即使文档没有提到它是必要的 完全没有变化。现在,当我打开应用程序时,我什至没有收到静默通知。 (在我打开应用程序时显示通知之前)

以上是关于静默推送不触发代码执行的主要内容,如果未能解决你的问题,请参考以下文章

执行代码以响应 iOS 通知

iOS静默推送通知在后台状态下每次都不会触发

尽管正在执行DataLayer推送,但未触发Google跟踪代码管理器代码

如果用户禁用它们,如何发送静默推送通知?

当应用程序未连接到 xcode 时,iOS 8 静默推送通知不会触发 didReceiveRemoteNotification 方法

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