关于iOS的后台下载和断点续传,说一说自己的理解

简介: 首先,后台下载和断点续传是两件事;这里放在一起说是为了图个方便,实际二者在技术实现上没有什么关联。目前我们的下载实现一般都是基于nsurlsession和iOS7+的,所以我们这里不考虑iOS6和以前的老系统,主要技术实现也是基于nsurlsession.先说后台下载:1. 在没有特别关注的情况下,可能很多开发者使用afnetworking下载的姿势并没有考虑到后台下载这一块。

首先,后台下载和断点续传是两件事;这里放在一起说是为了图个方便,实际二者在技术实现上没有什么关联。

目前我们的下载实现一般都是基于nsurlsession和iOS7+的,所以我们这里不考虑iOS6和以前的老系统,主要技术实现也是基于nsurlsession.


先说后台下载:

1. 在没有特别关注的情况下,可能很多开发者使用afnetworking下载的姿势并没有考虑到后台下载这一块。在默认情况(不做特别设置)下,afnetworking并未启用backgroundsession, 因此很可能你的app是不支持后台下载的。

2. nsurlsession对后台下载的支持主要通过 backgroundSessionConfiguration/backgroundSessionConfigurationWithIdentifier 类型的session来支持;通过该session来调用下载方法,实现几个下载相关的回调方法,也就可以实现基本的目的:应用切换到后台时仍然在下载(但下载完成后得不到回调和提醒)。

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                              didFinishDownloadingToURL:(NSURL *)location;

@optional
/* Sent periodically to notify the delegate of download progress. */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                                           didWriteData:(int64_t)bytesWritten
                                      totalBytesWritten:(int64_t)totalBytesWritten
                              totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;

/* Sent when a download has been resumed. If a download failed with an
 * error, the -userInfo dictionary of the error will contain an
 * NSURLSessionDownloadTaskResumeData key, whose value is the resume
 * data.
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                                      didResumeAtOffset:(int64_t)fileOffset
                                     expectedTotalBytes:(int64_t)expectedTotalBytes;


3. 如果需要下载完成后得到回调和提醒,或者更高级一点(应用程序被系统干掉等情况,还能够通过下载任务拉起并发送回调和提醒,而且系统在后台会生成一个快照,按home键查看时就仿佛这个应用被启动过一样。这里的内容是根据苹果官方答复和相关文档得到,系统干掉的场景笔者并未模拟),我们就需要进行额外的设置了。

- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler {
//  这里返回了session的identifier和completionBlock;其中的identifier可以用于匹配session,而completionBlock我们需要保存起来,到后面一个步骤需要调用之。
}

- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {
// 这里需要执行上一步保存的completionBlock:

根据苹果员工的回复,这里苹果需要用这个block实现两个功能:

a. 系统后台生成快照

b. 释放阻止应用挂起的断言(让应用继续在后台运行,节约系统资源)

  1. The system does two things in that completion handler:

    • It snapshots your UI for the benefit of the multitasking switcher

    • It releases the assertion that was preventing your app from being suspended

https://forums.developer.apple.com/thread/69825

}


在一次后台下载中方法的执行时序为:a.handleEventsForBackgroundURLSession ->b. URLSession: downloadTask: didFinishDownloadingToURL->c. URLSessionDidFinishEventsForBackgroundURLSession.

建议发送本地通知的动作统一放在b中,目前看放在a和c中应该也是可以的。


再来说一说断点续传:

1. 从协议层面来说,断点续传的实现都是通过http头里面的range来实现的。对于以前asi的实现和基于nsurlconnection的实现来说,我们都是通过手动保存当前大小然后填充到range的策略来实现断点续传功能的。

2. nsurlsession内置了对于断点续传的api支持,主要是通过resumedata和tmp中间文件。在nsurlsession暂停时,其中间文件的相关信息被保存到resumedata,我们只要通过这个resumedata,即可从之前的下载进度中恢复。也就是说1中的细节被封装在api内部了。

目前来看,基于nsurlsession的断点续传主要有两个问题需要考虑:

a. 程序退出(手动kill等)时需要自动保存resumedata,后续应用起来时再恢复之。

b. iOS10里面的resumedata的保存有点问题,需要特别处理,可以参考此demo:https://github.com/HustHank/BackgroundDownloadDemo.


其他细节暂时不再展开了,后面有机会再深入的说一说,大体方案就是这样,大家可以尽量参考苹果官方文档。


一些参考文档:

https://my.oschina.net/iOSliuhui/blog/469276  断点下载流程讲解
http://www.cocoachina.com/ios/20160503/16053.html  断点续传方案 ??? 不断保存?方案不可取! 程序被杀时主动保存!这里的ios应该为小写,被自动格式化成大写了
https://code.tutsplus.com/tutorials/ios-7-sdk-background-transfer-service--mobile-20595 后台传输服务
http://www.jianshu.com/p/1211cf99dfc3 下载相关,BackgroundDownloadDemo作者的分享
苹果论坛相关讨论
https://forums.developer.apple.com/thread/14854
https://forums.developer.apple.com/thread/69825





目录
相关文章
|
7月前
|
Android开发 iOS开发
ios后台播放声音的三种实现方式
ios后台播放声音的三种实现方式
552 1
|
7月前
|
iOS开发
iOS中如何显示后台返回的带有html标签的富文本字符串
iOS中如何显示后台返回的带有html标签的富文本字符串
68 0
|
7月前
|
定位技术 开发工具 iOS开发
ios9定位服务的app进入后台三分钟收不到经纬度,应用被挂起问题及解决方案
ios9定位服务的app进入后台三分钟收不到经纬度,应用被挂起问题及解决方案
61 0
|
7月前
|
存储 移动开发 JavaScript
【原生】sd.js帮助您简化繁重的获取数据、存储数据(CRUD)骚操作(吐槽~在安卓9.0以下或者IOS10.X以下手机端H5页面不支持,在这两种情况下的系统只能使用ajax或者原生js请求后台数据)
【原生】sd.js帮助您简化繁重的获取数据、存储数据(CRUD)骚操作(吐槽~在安卓9.0以下或者IOS10.X以下手机端H5页面不支持,在这两种情况下的系统只能使用ajax或者原生js请求后台数据)
|
Swift iOS开发
iOS OC混编Swift 后者无法走断点
iOS OC混编Swift 后者无法走断点
83 0
|
存储 缓存 iOS开发
iOS 轻量化动态图像下载缓存框架实现
日常开发过程中,图片的下载会占用大量的带宽,图片的加载会消耗大量的性能和内存,正确的使用图片显得尤为重要。 同样也经常需要在各类型控件上读取网络图片和处理本地图片,例如:UIImageView、UIBtton、NSImageView、NSButton等等。
iOS 轻量化动态图像下载缓存框架实现
|
iOS开发
iOS下载文件保存到手机文件指定目录
iOS下载文件保存到手机文件指定目录
1119 0
|
Web App开发 Android开发 iOS开发
iOS 后台程序
iOS 后台程序
176 0
|
Web App开发 弹性计算 Android开发
阿里云无影云桌面客户端下载Win/Mac/iOS/安卓/Web端均支持
阿里云无影客户端下载系统Win/Mac/iOS/安卓/Web端均支持
4656 0
阿里云无影云桌面客户端下载Win/Mac/iOS/安卓/Web端均支持