简体   繁体   English

来自后台推送的后台网络调用

[英]Background Network Call from Background Push

I have an application that communicates with the Apple Watch.我有一个与 Apple Watch 通信的应用程序。 When the main iOS app gets a remote notification, it fires off a network request using URLSession and then also sends the result to the watch.当主 iOS 应用程序收到远程通知时,它会使用URLSession触发网络请求,然后还将结果发送到手表。

The issue is that when the iOS app is in the background and the push notification is received, the network call is never made.问题是当 iOS 应用程序在后台并且收到推送通知时,永远不会进行网络调用。 I can see, via breakpoints, that the code is executed but not the code when data is received.我可以通过断点看到代码被执行,但不是在接收到数据时的代码。

I do have the content-available flag set and I have also tried using the URLSessionConfiguration.background without success.我确实设置了 content-available 标志,我也尝试使用URLSessionConfiguration.background没有成功。

var config:URLSessionConfiguration!
var session:URLSession?

private func configureSession()
{
        self.config = URLSessionConfiguration.background(withIdentifier: "backgroundFetch")
        //self.config = URLSessionConfiguration.default
        self.config.sessionSendsLaunchEvents = true
        self.config.timeoutIntervalForRequest = 15.0
        self.config.timeoutIntervalForResource = 15.0

        self.session = URLSession(configuration: self.config, delegate: self, delegateQueue: nil)
}

You can see above that I tried it with both default and the background mode.您可以在上面看到我在默认和后台模式下都尝试过。

func getCoordinatesForID(_ trackID:String, withPassCode passCode:String, andMyID myID:String)
{
    let url = self.WEB_DOMAIN+"getcoord"
    let hash = SecurityModel.sha256(myID+trackID+passCode)!
    var request = URLRequest(url: URL(string: url)!)

    request.httpMethod = "POST"
    request.setValue("application/x-www-form-urlencoded;charset=utf-8", forHTTPHeaderField: "Content-Type")

    let postDataStr = "auth=\(hash)&id=\(myID)&trk=\(trackID)&code=\(passCode)"

    let requestBodyData = postDataStr.data(using: String.Encoding.utf8)
    request.httpBody = requestBodyData

    let postDataTask = self.session!.dataTask(with: request)
    postDataTask.taskDescription = "getCoordinates"
    postDataTask.resume()
}

The above function is called when in the background but this is where things stop.上面的函数在后台被调用,但这就是事情停止的地方。 Nothing is ever received.什么都没有收到。 Works fine in foreground.在前台工作正常。

I do implement the below is neither is called when in the background.我确实实现了下面的既不是在后台调用的。

func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)

and

func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)

Update:更新:

Per the comment from Edward I did update capabilities to include "background fetch" although the documentation on downloading after a notification did not indicate this was necessary.根据爱德华的评论,我确实更新了功能以包括“后台获取”,尽管通知后下载的文档并未表明这是必要的。 That seems to have worked but only in part and so a problem persists.这似乎奏效了,但只是部分有效,因此问题仍然存在。

func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) 

The above is getting called but is throwing the error: "Lost connection to background transfer service" .上面被调用但抛出错误: "Lost connection to background transfer service" Happens 100% of the time when in the background state but not the foreground. 100% 发生在后台状态而不是前台状态。

 func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)

The above which I need and is called first before the method above it, is not called at all.我需要并在上面的方法之前首先调用的上面,根本没有被调用。 So overall things have progressed a bit further but still don't work in the same way as it does when in the foreground.因此,总体而言,事情已经取得了进一步的进展,但仍然不像在前台时那样以相同的方式工作。

Solution:解决方案:

The solution was to remove the timeoutIntervalForRequest and timeoutIntervalforResource Despite the fact that I never waited the 15 seconds I set before the issue resulted, removing these allowed the process to work correctly in the background.解决方案是删除timeoutIntervalForRequesttimeoutIntervalforResource尽管事实上我从来没有等待过我在问题产生之前设置的 15 秒,但删除这些允许进程在后台正常工作。 Additionally I am able to use the standard URLSessionConfiguration.default rather than the .background.此外,我可以使用标准的URLSessionConfiguration.default而不是 .background。

So in the end adding the "background fetch" capability and removing the timeouts resolved the issue.所以最后添加“后台获取”功能并删除超时解决了这个问题。

I found after more tests with the ideas above that things were not working consistently.经过对上述想法的更多测试后,我发现事情并不一致。 The issue is that I was using URLSessionDataTask which, as it turns out, is not support in the background.问题是我使用的是URLSessionDataTask ,事实证明,它在后台URLSessionDataTask Per Apple's documentation:根据 Apple 的文档:

Data tasks request a resource, returning the server's response as one or more NSData objects in memory.数据任务请求资源,将服务器的响应作为内存中的一个或多个 NSData 对象返回。 They are supported in default, ephemeral, and shared sessions, but are not supported in background sessions.它们在默认、临时和共享会话中受支持,但在后台会话中不受支持。

To solve this problem I had to create a URLSessionDownloadTask and use its associated delegate为了解决这个问题,我必须创建一个URLSessionDownloadTask并使用其关联的委托

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL)

With the above the network calls worked properly when the app was in the background.当应用程序在后台时,网络调用可以正常工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM