簡體   English   中英

當應用程序在后台時,來自 iOS 推送通知操作的 Http 請求

[英]Http request from iOS push notification action when app is in background

我的 iOS 應用程序可以接收帶有操作按鈕的推送通知:

帶有操作按鈕的推送通知

按鈕點擊通過 UrlSession 和數據任務發送 post http 請求。 當應用程序暫停或未運行時,它運行良好。 但是當應用程序處於后台時它不起作用,例如當用戶剛剛從底部向上滑動(或按下主頁按鈕)時。 推送操作處理但不發送 http 請求。

從我 iPhone 的控制台 os_logs 我看到 UrlSession 無法從后台建立連接並拋出錯誤代碼 =-1005“網絡連接丟失。”。 只要我殺死應用程序,它就可以。 我嘗試了不同的 url 會話配置、后台 url 會話、后台任務,但沒有任何效果。 我發現的唯一解決方法是使用applicationDidEnterBackground方法中的exit(0) ,但強烈不建議以編程方式終止應用程序。

問題:當應用程序在后台時,如何通過推送通知操作建立 http 連接?

我的代碼:

class NotificationService: NSObject, UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        // notification processing if app is in foreground
        ...
    }
    
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        let requestId = String(describing: response.notification.request.content.userInfo["requestId"] ?? "")
        switch response.actionIdentifier {
        case "CONFIRM_ACTION":
            confirmAuthenticationRequest(requestId: requestId, isConfirmed: true)
        case "REJECT_ACTION":
            confirmAuthenticationRequest(requestId: requestId, isConfirmed: false)
        default:
            // on notification tap
            ...
        }
        completionHandler()
    }

private func confirmAuthenticationRequest(requestId: String, isConfirmed: Bool) {
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        let json: [String: Any] = [
            "requestId": requestId,
            "deny": !isConfirmed
        ]
        request.httpBody = try? JSONSerialization.data(withJSONObject: json)
        request.addValue("application/json", forHTTPHeaderField: "content-type")
        
        let dataTask = urlSession.dataTask(with: request)
        dataTask.resume()
    }
}

最后我找到了答案。 推送通知操作不穩定的原因是從userNotificationCenterDidReceiveResponse方法調用completionHandler錯誤方式。 當執行像 http 請求這樣的異步操作時,您必須在操作完成后(而不是在操作調用后)和從主線程調用completionHandler 這是工作示例:

class NotificationService: NSObject, UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        let requestId = String(describing: response.notification.request.content.userInfo["requestId"] ?? "")
        switch response.actionIdentifier {
        case "CONFIRM_ACTION":
            confirmAuthenticationRequest(requestId: requestId, isConfirmed: true, completion: completionHandler)
        case "REJECT_ACTION":
            confirmAuthenticationRequest(requestId: requestId, isConfirmed: false, completion: completionHandler)
        default:
            // on notification tap
            ...
            completionHandler()
        }
    }

private func confirmAuthenticationRequest(requestId: String, isConfirmed: Bool, completion: @escaping () -> Void) {
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        let json: [String: Any] = [
            "requestId": requestId,
            "deny": !isConfirmed
        ]
        request.httpBody = try? JSONSerialization.data(withJSONObject: json)
        request.addValue("application/json", forHTTPHeaderField: "content-type")
        
        let dataTask = urlSession.dataTask(with: request) { _, _, _ in
            DispatchQueue.main.async {
                completion()
            }
        }
        dataTask.resume()
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM