通知操作后台任务未按预期运行

时间:2017-07-26 15:15:58

标签: ios swift3 alamofire

更新

在发表一些评论后,我将resolveVisita方法更改为在后台使用URLSession,但看起来后台会话只会在应用程序位于前台时启动,这里是更新后的方法在点击通知操作时运行:

static func resolverVisita(idMensagem: String, resposta: String, liberar: Bool, view: UIViewController?) {

    //let configuration = URLSessionConfiguration.background(withIdentifier: "url_session_resolve_visita")
    //var backgroundSession = URLSession(configuration: configuration)

    // Set up the URL request
    let todoEndpoint: String = URL_RESPONDE_VISITA

    guard let url = URL(string: todoEndpoint) else {
        print("Error: cannot create URL")
        return
    }

    var urlRequest = URLRequest(url: url)
    urlRequest.httpMethod = "POST"

    let postString = "userUUID=\(SessionManager.getUsrUUID())&devUUID=\(devUUID)&msgID=\(idMensagem)&tarefa=\(liberar ? "L" : "B")&resposta=\(resposta)"

    urlRequest.httpBody = postString.data(using: .utf8)

    let config = URLSessionConfiguration.background(withIdentifier: "\(Bundle.main.bundleIdentifier!).responde_visita")

    let session = URLSession(configuration: config)

    /*
    let task = URLSession.shared.dataTask(with: urlRequest) { data, response, error in
        guard let data = data, error == nil else {                                                 // check for fundamental networking error
            print("error=\(error)")
            return
        }

        if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {           // check for http errors
            print("statusCode should be 200, but is \(httpStatus.statusCode)")
            print("response = \(response)")
        }

        let responseString = String(data: data, encoding: .utf8)
        print("responseString = \(responseString)")
    }*/

    let task = session.dataTask(with: urlRequest)
    task.resume()

}

注释掉的代码似乎有时会起作用,但看起来它不是正确的方法。

更新结束

所以我有一个接收通知的应用程序,它有2个动作,并且在用户响应时,应用程序应该向服务器发送响应,最好是在后台。

我遇到一个问题,无论什么时候点击某个操作,有时在打开应用程序之前都不会调用userNotificationCenter方法,有时它会运行,但是 Alamofire 服务器调用没有得到处理,然后如果我打开应用程序控制台中显示有关Alamofire调用的一些错误,但是如果我点击操作然后打开应用程序足够快它按预期工作。

Console output errors

我已经在Xcode的应用功能下启用了后台获取远程通知

这就是我为通知创建操作的方式:

 let liberar = UNTextInputNotificationAction(identifier:"liberar", title:"Liberar",options:[.authenticationRequired],
                                                     textInputButtonTitle: "Liberar",
                                                     textInputPlaceholder: "Resposta")

    let bloquear = UNTextInputNotificationAction(identifier: "bloquear", title: "Bloquear", options: [.destructive],
                                                     textInputButtonTitle: "Bloquear",
                                                     textInputPlaceholder: "Resposta")

这是我的UNUserNotificationCenterDelegate协议实施:

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

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

    // Print message ID.
    if let messageID = userInfo[gcmMessageIDKey] {
        print("Message ID: \(messageID)")
    }

    // Print full message.
    print(userInfo)

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

func userNotificationCenter(_ center: UNUserNotificationCenter,
                            didReceive response: UNNotificationResponse,
                            withCompletionHandler completionHandler: @escaping () -> Void) {

    let userInfo = response.notification.request.content.userInfo
    let acao = response.actionIdentifier

    //let request = response.notification.request

    // Print message ID.
    if let messageID = userInfo[gcmMessageIDKey] {
        print("Message ID: \(messageID)")
    }

    print(acao)

    if acao == "liberar" {
        // Print full message.


        let textResponse = response as! UNTextInputNotificationResponse

        print("Liberando Visita")
        AppConfig.resolverVisita(idMensagem: (userInfo["msgid"] as? String)!, resposta: textResponse.userText, liberar: true, view: nil)
    }

    else if acao == "bloquear" {
        let textResponse = response as! UNTextInputNotificationResponse

        print("Bloqueando Visita")
        AppConfig.resolverVisita(idMensagem: (userInfo["msgid"] as? String)!, resposta: textResponse.userText, liberar: false, view: nil)

        //let newContent = request.content.mutableCopy() as! UNMutableNotificationContent
        //print(textResponse.userText)

    }

    completionHandler()
}}

这是resolveVisita方法,它基本上只是收集一些数据并使用Alamofire通过POST请求发送。

static func resolverVisita(idMensagem: String, resposta: String, liberar: Bool, view: UIViewController?) {

    if view != nil {
        showLoading(mensagem: NSLocalizedString("Processando...", comment: ""), view: view!)
    }
    //Parameters to be sent
    let parameters: Parameters=[
        "userUUID":SessionManager.getUsrUUID(),
        "devUUID":devUUID,
        "msgID": idMensagem,
        "resposta": resposta,
        "tarefa": liberar ? "L" : "B"
        ];

    //Sending http post request
    Alamofire.request(URL_RESPONDE_VISITA, method: .post, parameters: parameters).responseJSON{
        response in
        //printing response
        print(response)

        //getting the json value from the server
        if let result = response.result.value {

            //converting it as NSDictionary
            let jsonData = result as! NSDictionary

            var mensagem : String = "Solicitacao resolvida com sucesso"

            //displaying the message in label
            if((jsonData["error"] as! Bool)){

                mensagem = jsonData["error_msg"] as! String

                if view == nil {
                    Notificacoes.notificaErroSolicitavao(msgId: idMensagem, errMsg: mensagem)
                }

            }

            if view != nil {
                view?.dismiss(animated: false){
                    showAlert(mensagem: NSLocalizedString(mensagem, comment: ""), view: view!, okMsg: NSLocalizedString("Voltar", comment: ""), segue: "voltarParaLogin")
                }
            }
            else{
                print(mensagem)
            }

        }
    }

}

如果我只是将.foreground选项添加到选择后打开应用程序的操作,问题就解决了,但我真的认为应用程序无需为此任务打开。< / p>

1 个答案:

答案 0 :(得分:0)

所以过了一段时间我决定以一种清醒的头脑回到这个问题,我发现我做错了什么,我试图在后台创建URLSession的实例锁定屏幕,并创建“同一会话”的新实例,以解决这个问题,我所要做的就是创建一个URLSession的静态实例,然后在需要时使用它。

我是这样创造的。

 static let resolveVisitaSession = URLSession(configuration: URLSessionConfiguration.background(withIdentifier: "br.com.freaccess.resolveVisitaRequest"))

这是在UNNotificationAction上选择的方法,我在那里使用我的URLSession。

static func resolverVisita(idMensagem: String, resposta: String, liberar: Bool) {
    print("Entered resolveVisita method")

    // Set up the URL request
    let todoEndpoint: String = URL_RESPONDE_VISITA

    guard let url = URL(string: todoEndpoint) else {
        print("Error: cannot create URL")
        return
    }

    var urlRequest = URLRequest(url: url)
    urlRequest.httpMethod = "POST"

    let postString = "userUUID=\(SessionManager.getUsrUUID())&devUUID=\(devUUID)&msgID=\(idMensagem)&tarefa=\(liberar ? "L" : "B")&resposta=\(resposta)&skipSocket=true"

    urlRequest.httpBody = postString.data(using: .utf8)

    resolveVisitaSession.dataTask(with: urlRequest).resume()
}