iOS 7 SDK:后台传输服务(Background Transfer Service)
2014-05-23 11:40
274 查看
http://www.cocoachina.com/applenews/devnews/2013/1120/7380.html
本文主要说说如何使用iOS 7多任务处理中的后台传输服务(Background Transfer Service),并讲述如何创建一个app--当不在前台运行时也能下载文件的app。一旦完成全部下载,还会弹出一个通知信息提醒用户。
后台传输服务最初是由iOS 6引入的,允许app在前台和后台传输文件,但有时间限制。最大的问题是“limited minutes”不允许用户下载或上传比较大的文件。这也是苹果在iOS 7中改进这项功能的原因。
在iOS 7中,该功能发生了以下变化:
iOS系统管理下载和上传内容
当用户关闭app后继续传输内容
没有时间限制
可以随时加入队列(前台和后台)
为了处理认证、错误或者completion事件,app会被唤醒
该app包含一个Progress View
后台传输服务可以用来处理几个不同的有用的任务,比如上传照片或视频,结合后台获取和远程通知,以及保持应用更新(比如购买书籍、TV shows、游戏内容以及其他)。
1.设置工程
要创建该服务,我们需要一个single view,并包含如下属性:
A ViewController
A NavigationController
A Bar Item (to start the Download)
An UIDocumentInterationController (to open the PDF document download)
首先,开始一个新的Xcode iPhone工程。然后创建一个Single View app。接着到Main.Storyboard,在view中添加一些对象。想要添加NavigationController,选中Default View Controller。在Xcode菜单中,选择Editor > Embed In > Navigation Controller。把Bar Item和Progress View拖放至View Controller。一旦完成,View Controller
看起来是以下样式:
然后,添加必要的属性来与我们之前添加的对象进行交互。在ViewController.h添加以下代码:
现在改变ViewController.m的视图。你会看到一个警示,不过不用担心,我们稍后再修复它。回到Main.Storyboard,并链接好相关的属性和动作,这些步骤比较琐碎。
2.NSURLSession
NSURLSession类和相关的类提供了一个可以通过HTTP上传或者下载内容的API,主要用来管理一系列传输任务。我们需要创建三个与这个类直接相关的对象:NSURLSession, NSURLSessionDownloadTask以及 UIDocumentInteractionController。
ViewController.h看起来会是这样:
另外,你还要声明四个协议:NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDownloadDelegate以及UIDocumentInteractionControllerDelegate。
@interface应该是像这样的:
我们将要添加的属性对于session的实例化和操作,以及下载处理非常有好处:可以恢复、暂停、取消或检索状态信息。最后一个属性--UIDocumentInterationController在本文中是用来展示下载的PDF文档。
打开ViewController.m。第一个需要完成的任务是把字符串添加至文件下载的位置。你应该使用一个标准的苹果PDF。
在viewDidLoad 方法中, 我们实例化并设置session和progress view:
由于你执行了一个并不存在的backgroundSession方法,所以你必须声明它,该方法主要用来产生一个在后台运行的会话。NSURLSessionConfiguration接收的NSString参数是我们创建的会话的ID,对于每个NSURLSession实例,这个ID必须是独一无二的。
完整的方法如下:
(IBAction)start:(id)sender方法开启了文档下载。你将会初始化一个NSURL和 NSURLRequest,并使用downloadTask属性把请求对象传递至downloadTaskWithRequest方法,完整的方法如下:
3.协议
在这一点上,你会注意到3个警示,它们表示应该执行协议方法。NSURLSessionDownloadDelegate协议定义了处理下载任务的方法。想要执行下载,它需要使用三个委托方法,所以添加以下三个方法:
1. (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:
(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
2. (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)downloadURL {
3. (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite方法主要用来跟踪整个下载进程,同时也相应地更新
progressView。整个方法如下:
4.下载任务
(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)downloadURL方法处理数据(origin and destination)。它在下载完成后控制文件。简化起见,它通知delegate下载任务已经完成。它包含已经完成的session task和download task,以及文件URL(可以在此找到临时文件)。看起来应该是这样:
最后 (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes必须也被声明,但要清楚我们不会进一步使用它。
5.Session Tasks
你几乎完成了这个类,只剩下两个方法: (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error和 - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session.
第一个方法通知delegate任务已经完成了数据传输,你也应该用它来跟踪发生的任何错误。
最后,你需要添加 (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session方法,它通知delegate所有的session消息列队已经交付。为了加载UILocalNotification,它实例化AppDelegate.你应该使用如下方法:
由于你没有把AppDelegate.h移植到你的类中,所以会出现几个错误:
把两个对象添加至AppDelegate.h:
在AppDelegate.m中,你应该执行delegate方法(void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler.它通知delegate--与URL session相关的事件正等待处理,并调用自定义方法(presentNotification)通知用户,在文件加载完毕时。完整的方法如下:
6.本地通知
presentNotification方法用UILocalNotification类来创建本地通知。它创建一个声音,并使用在通知中使用徽标系统--badge system,完整方法如下:
顺便提下,为了重新计算app icon左上角的counter,你必须在AppDelegate中把下边一行代码添加至 (void)applicationDidBecomeActive:(UIApplication *)application方法。
通知应该类似于以下这张图:
现在运行app并测试后台加载。
总结
最后,你应该理解后台传输服务以及知道如何使用它。
原文:iOS 7 SDK: Background Transfer Service
本文主要说说如何使用iOS 7多任务处理中的后台传输服务(Background Transfer Service),并讲述如何创建一个app--当不在前台运行时也能下载文件的app。一旦完成全部下载,还会弹出一个通知信息提醒用户。
后台传输服务最初是由iOS 6引入的,允许app在前台和后台传输文件,但有时间限制。最大的问题是“limited minutes”不允许用户下载或上传比较大的文件。这也是苹果在iOS 7中改进这项功能的原因。
在iOS 7中,该功能发生了以下变化:
iOS系统管理下载和上传内容
当用户关闭app后继续传输内容
没有时间限制
可以随时加入队列(前台和后台)
为了处理认证、错误或者completion事件,app会被唤醒
该app包含一个Progress View
后台传输服务可以用来处理几个不同的有用的任务,比如上传照片或视频,结合后台获取和远程通知,以及保持应用更新(比如购买书籍、TV shows、游戏内容以及其他)。
1.设置工程
要创建该服务,我们需要一个single view,并包含如下属性:
A ViewController
A NavigationController
A Bar Item (to start the Download)
An UIDocumentInterationController (to open the PDF document download)
首先,开始一个新的Xcode iPhone工程。然后创建一个Single View app。接着到Main.Storyboard,在view中添加一些对象。想要添加NavigationController,选中Default View Controller。在Xcode菜单中,选择Editor > Embed In > Navigation Controller。把Bar Item和Progress View拖放至View Controller。一旦完成,View Controller
看起来是以下样式:
然后,添加必要的属性来与我们之前添加的对象进行交互。在ViewController.h添加以下代码:
@property (weak, nonatomic) IBOutlet UIProgressView *progressView; - (IBAction)start:(id)sender;
现在改变ViewController.m的视图。你会看到一个警示,不过不用担心,我们稍后再修复它。回到Main.Storyboard,并链接好相关的属性和动作,这些步骤比较琐碎。
2.NSURLSession
NSURLSession类和相关的类提供了一个可以通过HTTP上传或者下载内容的API,主要用来管理一系列传输任务。我们需要创建三个与这个类直接相关的对象:NSURLSession, NSURLSessionDownloadTask以及 UIDocumentInteractionController。
ViewController.h看起来会是这样:
@property (nonatomic) NSURLSession *session; @property (nonatomic) NSURLSessionDownloadTask *downloadTask; @property (strong, nonatomic) UIDocumentInteractionController *documentInteractionController;
另外,你还要声明四个协议:NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDownloadDelegate以及UIDocumentInteractionControllerDelegate。
@interface应该是像这样的:
@interface ViewController : UIViewController < NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDownloadDelegate,UIDocumentInteractionControllerDelegate>
我们将要添加的属性对于session的实例化和操作,以及下载处理非常有好处:可以恢复、暂停、取消或检索状态信息。最后一个属性--UIDocumentInterationController在本文中是用来展示下载的PDF文档。
打开ViewController.m。第一个需要完成的任务是把字符串添加至文件下载的位置。你应该使用一个标准的苹果PDF。
static NSString *DownloadURLString = @"https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/ObjC_classic/FoundationObjC.pdf";
在viewDidLoad 方法中, 我们实例化并设置session和progress view:
self.session = [self backgroundSession]; self.progressView.progress = 0; self.progressView.hidden = YES;
由于你执行了一个并不存在的backgroundSession方法,所以你必须声明它,该方法主要用来产生一个在后台运行的会话。NSURLSessionConfiguration接收的NSString参数是我们创建的会话的ID,对于每个NSURLSession实例,这个ID必须是独一无二的。
完整的方法如下:
- (NSURLSession *)backgroundSession { static NSURLSession *session = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.example.apple-samplecode.SimpleBackgroundTransfer.BackgroundSession"]; session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; }); return session; }
(IBAction)start:(id)sender方法开启了文档下载。你将会初始化一个NSURL和 NSURLRequest,并使用downloadTask属性把请求对象传递至downloadTaskWithRequest方法,完整的方法如下:
- (IBAction)start:(id)sender { if (self.downloadTask) { return; } NSURL *downloadURL = [NSURL URLWithString:DownloadURLString]; NSURLRequest *request = [NSURLRequest requestWithURL:downloadURL]; self.downloadTask = [self.session downloadTaskWithRequest:request]; [self.downloadTask resume]; self.progressView.hidden = NO; }
3.协议
在这一点上,你会注意到3个警示,它们表示应该执行协议方法。NSURLSessionDownloadDelegate协议定义了处理下载任务的方法。想要执行下载,它需要使用三个委托方法,所以添加以下三个方法:
1. (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:
(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
2. (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)downloadURL {
3. (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite方法主要用来跟踪整个下载进程,同时也相应地更新
progressView。整个方法如下:
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { if (downloadTask == self.downloadTask) { double progress = (double)totalBytesWritten / (double)totalBytesExpectedToWrite; NSLog(@"DownloadTask: %@ progress: %lf", downloadTask, progress); dispatch_async(dispatch_get_main_queue(), ^{ self.progressView.progress = progress; }); } }
4.下载任务
(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)downloadURL方法处理数据(origin and destination)。它在下载完成后控制文件。简化起见,它通知delegate下载任务已经完成。它包含已经完成的session task和download task,以及文件URL(可以在此找到临时文件)。看起来应该是这样:
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)downloadURL { NSFileManager *fileManager = [NSFileManager defaultManager]; NSArray *URLs = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]; NSURL *documentsDirectory = [URLs objectAtIndex:0]; NSURL *originalURL = [[downloadTask originalRequest] URL]; NSURL *destinationURL = [documentsDirectory URLByAppendingPathComponent:[originalURL lastPathComponent]]; NSError *errorCopy; // For the purposes of testing, remove any esisting file at the destination. [fileManager removeItemAtURL:destinationURL error:NULL]; BOOL success = [fileManager copyItemAtURL:downloadURL toURL:destinationURL error:&errorCopy]; if (success) { dispatch_async(dispatch_get_main_queue(), ^{ //download finished - open the pdf self.documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:destinationURL]; // Configure Document Interaction Controller [self.documentInteractionController setDelegate:self]; // Preview PDF [self.documentInteractionController presentPreviewAnimated:YES]; self.progressView.hidden = YES; }); } else { NSLog(@"Error during the copy: %@", [errorCopy localizedDescription]); } }
最后 (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes必须也被声明,但要清楚我们不会进一步使用它。
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes { }
5.Session Tasks
你几乎完成了这个类,只剩下两个方法: (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error和 - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session.
第一个方法通知delegate任务已经完成了数据传输,你也应该用它来跟踪发生的任何错误。
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { if (error == nil) { NSLog(@"Task: %@ completed successfully", task); } else { NSLog(@"Task: %@ completed with error: %@", task, [error localizedDescription]); } double progress = (double)task.countOfBytesReceived / (double)task.countOfBytesExpectedToReceive; dispatch_async(dispatch_get_main_queue(), ^{ self.progressView.progress = progress; }); self.downloadTask = nil; }
最后,你需要添加 (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session方法,它通知delegate所有的session消息列队已经交付。为了加载UILocalNotification,它实例化AppDelegate.你应该使用如下方法:
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session { AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; if (appDelegate.backgroundSessionCompletionHandler) { void (^completionHandler)() = appDelegate.backgroundSessionCompletionHandler; appDelegate.backgroundSessionCompletionHandler = nil; completionHandler(); } NSLog(@"All tasks are finished"); }
由于你没有把AppDelegate.h移植到你的类中,所以会出现几个错误:
#import "AppDelegate.h"
把两个对象添加至AppDelegate.h:
@property (strong, nonatomic) UIWindow *window; @property (copy) void (^backgroundSessionCompletionHandler)();
在AppDelegate.m中,你应该执行delegate方法(void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler.它通知delegate--与URL session相关的事件正等待处理,并调用自定义方法(presentNotification)通知用户,在文件加载完毕时。完整的方法如下:
- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler { self.backgroundSessionCompletionHandler = completionHandler; //add notification [self presentNotification]; }
6.本地通知
presentNotification方法用UILocalNotification类来创建本地通知。它创建一个声音,并使用在通知中使用徽标系统--badge system,完整方法如下:
-(void)presentNotification{ UILocalNotification* localNotification = [[UILocalNotification alloc] init]; localNotification.alertBody = @"Download Complete!"; localNotification.alertAction = @"Background Transfer Download!"; //On sound localNotification.soundName = UILocalNotificationDefaultSoundName; //increase the badge number of application plus 1 localNotification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1; [[UIApplication sharedApplication] presentLocalNotificationNow:localNotification]; }
顺便提下,为了重新计算app icon左上角的counter,你必须在AppDelegate中把下边一行代码添加至 (void)applicationDidBecomeActive:(UIApplication *)application方法。
application.applicationIconBadgeNumber = 0;
通知应该类似于以下这张图:
现在运行app并测试后台加载。
总结
最后,你应该理解后台传输服务以及知道如何使用它。
原文:iOS 7 SDK: Background Transfer Service
相关文章推荐
- iOS 7 SDK:后台传输服务(Background Transfer Service)
- iOS 7 SDK:后台传输服务(Background Transfer Service)
- iOS 7 SDK:后台传输服务
- Windows Phone 官方示例学习:Background Transfer Service Sample(后台传输)
- iOS 后台传输服务
- iOS开发-进阶:iOS7中的多任务 - Background Fetch,Silent Remote Notifications,Background Transfer Service
- iOS 7 SDK: 如何使用后台获取(Background Fetch)
- iOS:应用沉睡之时 后台传输服务
- iOS 7 SDK: 如何使用后台获取(Background Fetch)
- iOS 7 SDK: 如何使用后台获取(Background Fetch)
- win10偷跑流量并且Background Intelligent Transfer Service服务无法关闭
- iOS 7 SDK: 如何使用后台获取(Background Fetch)
- iOS 7 SDK: 如何使用后台获取(Background Fetch)
- iOS 7.0 Background Transfer Service
- 重新安装 BITS(background intelligent transfer service) 服务
- iOS 7 SDK: 如何使用后台获取(Background Fetch)
- iOS开发-进阶:iOS7中的多任务 - Background Fetch,Silent Remote Notifications,Background Transfer Service
- iOS 7 SDK: 如何使用后台获取(Background Fetch)
- iOS中的多任务: Background Fetch,Silent Remote Notifications,Background Transfer Service
- iOS 7 SDK: 如何使用后台获取(Background Fetch)