iOS 13后台下载问题

6

我有一个同步功能,其中一系列下载在后台进行。

为此,我使用以下配置创建了一个带背景配置的URLSession实例:

let config = URLSessionConfiguration.background(withIdentifier: "BackgroundSessionDL")
config.httpMaximumConnectionsPerHost = 20

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

每个下载任务(可能有几百个)都按以下方式添加:

var request = URLRequest(url: url)
request.addValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")

let downloadTask = self.session.downloadTask(with: request)
downloadTask.resume()

这段代码在iOS 12或更早的版本上运行得非常完美——对于已添加的任务,下载会持续进行,即使在后台也是如此。但是,在iOS 13中会出现以下问题:
  1. 应用程序一旦进入后台,下载就会停止。
  2. 如果有任何下载任务正在进行中并将应用程序置于后台,则即使在将应用程序再次带回前台后,也不会观察到与回调相关的日志。
我试图搜索苹果是否为iOS 13引入了任何新的类/框架来进行后台任务下载,但是没有找到任何信息。另外,在早期版本中用于代表后台下载任务的类,在iOS 13中仍未过时,并且是搜索iOS 13上后台下载唯一的结果。同样,用于HTTP会话的后台配置也没有过时。因此,我认为当前的后台下载实现是苹果推荐的方法。(据我理解,“BGTaskScheduler”不适用于此,请纠正我。)
那么,这是否是由于iOS 13中新引入的错误? 还是Apple预计对iOS 13特定于此的实现进行更改?
编辑:
我已经添加了"handleEventsForBackgroundURLSession"回调。发现在iOS 13上不打印相应的日志,并且应用程序大小在设置中也不会增加。因此,似乎下载不会在后台继续进行,与未调用与下载相关的回调无关。

你解决了如何克服这个问题吗?我也遇到了同样的问题,已经花了几天时间试图解决它... 在iOS13上一切都运行得很完美。 - Exception
1个回答

3
我想如果您在前台运行应用程序,那么一切都按预期工作,但是一旦将应用程序放入后台,则不再接收任何回调。
BackgroundDownloader仅在应用程序处于前台时才起作用,但是当应用程序进入暂停/后台状态时有特定的支持。
当应用程序处于暂停/终止状态并且下载完成时,iOS将通过调用以下内容唤醒应用程序(后台中):
class AppDelegate: UIResponder, UIApplicationDelegate { 

    func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
        //TODO: Handle processing downloads
    }
}

在iOS12和iOS13之间的行为变化可能与某些API的更改无关,只是由于应用程序在不处于前台时采取了更积极的省电策略。
修改URLSession后台配置标识符。将isDiscretionary设置为false,以避免操作系统因电池或性能原因而安排后台请求传输。最重要的一个是将shouldUseExtendedBackgroundIdleMode设置为true。这是使TCP套接字在应用程序锁定或挂起时保持打开状态的终极方法。

感谢您的回复。您的问题让我意识到问题有点模糊,所以我已经重新措辞了。我已经添加了“handleEventsForBackgroundURLSession”回调,并发现相应的日志没有打印出来。 - Harish J
你能验证所有后台下载是否都完成了吗?如果其中一个挂起或失败,它将阻止触发后台会话的完成。委托方法只有在所有操作完成时才会被调用,这意味着你的应用程序不会被激活。你是否检查设备控制台是否有一些诊断错误信息? - cristallo
嗨cristallo,后台下载没有完成(大约有几百个文件,其中至少有2-3个同时开始)。当应用程序进入后台时,我看不到任何正在进行的下载更新。这可以从设置中的应用程序大小看出来。我想找出原因...为什么在将应用程序放到后台时下载不会继续。 - Harish J
你是否正确配置了urlsession的shouldUseExtendedBackgroundIdleMode和discretionary mode? - cristallo
是的,我尝试过 shouldUseExtendedBackgroundIdleMode。同时,我也尝试了 isDiscretionary 的 true 和 false 两个值。但是它还是不起作用。我无法看到方法的日志 - func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL),该方法在完成单个任务后被调用。 - Harish J
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接