iOS7 新後臺及下載SDK介紹

在iOS7以前的系統中,App默認是不能後臺運行的,如果要後臺運行,可以採用以下兩類方法:

  (1)使用beginBackgroundTaskWithExpirationHandler函數,向系統申請一段時間來執行需要後臺運行的操作,這種方法的缺點是,後臺操作最多隻能運行10分鐘,超過10分鐘之後App會休眠。使用這種方法需要APPNAME-info.plist中設置Application does not run in background爲NO,然後在適當的時間調用beginBackgroundTaskWithExpirationHandler函數。

 (2)將App的後臺運行模式設置爲audio 、VOIP、location、Newstand等。使用這種方法,可以無限制的在後臺運行,以audio爲例,將plist中的Required background modes項目設置爲App plays audio or streams audio/video using AirPlay,並且在進入後臺時播放無聲音樂,就可以讓App一直運行。這種方法的缺點是,如果使用不當,可能會被AppStore拒絕。因爲審覈時是可以通過靜態分析知道使用了哪些API的,如果一個程序本來就不是音樂類的,卻使用了播放音樂的API後臺播音樂,有可能就被拒絕,如果想要繞過這個限制,可以向APP增加播放音樂的功能,但這樣實際是增加了無用功能。

    在iOS7以後,系統增加了兩種後臺的模式,一種是Background fetch ,另一種是Remote notification,下面分別介紹。

    Background fetch:  設置了這種後臺方式之後,當App休眠之後,會隔一段時間被系統喚醒,從而執行一段短時間操作。喚醒的間隔由系統決定,App中可以設置[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];,但即使設置了,間隔也不確定是多少。另外,App被喚醒後,可以執行操作的時間也不長,文檔上描述的30秒左右(實際上更長也可以,但是可能會降低以後被喚醒的機率)。

  Remote notification:在iOS7以前,當系統收到推送消息後,會立即彈出消息提示用戶,用戶點擊消息之後,就可以啓動App,然後加載數據。使用了這種新的後臺模式之後,當系統收到推送消息之後,會喚醒App,給App一個機會執行一部分操作,等操作之後才提醒用戶,而且還支持silent模式,即執行完操作之後,完全不對用戶做任何提醒,默默的就在後臺把活幹完了。

   除了增加了上述的兩種新後臺模式以外,ios7還增加了一下傳輸數據的方法,即Background Transfer service 。

(1)Background Transfer service概述

      這種方法的名字很容易讓人誤解,以爲是App進入後臺時,使用這種方法進行數據傳輸。實際上,這種方法與後臺無關。 當App使用了這種方法後,可以將一個下載任務交給系統的獨立進程去下載,不管App在前臺、休眠、以及crash,下載過程都在進行,因爲是系統的獨立進程在爲App進行下載。當系統的下載任務結束或者出錯時,系統會喚醒App,調用其中的函數,讓App做一部分處理,比如讓App重新添加其他任務。這裏有一個缺點就是,如果因爲沒有網絡導致系統下載失敗了,系統即使喚醒了App,App也是沒有辦法下載的,然後App會進入休眠,即使後面有了網絡,系統也不會繼續下載,因爲只要系統向App發出了失敗的信號,除非App 調用resume函數來恢復下載過程,系統是不會自己恢復下載的。這裏就需要用到前面提到的fetch後臺模式,讓App過一段時間被系統喚醒,然後App就可以去檢查網絡,當有網時恢復下載過程。

(2)相關類介紹

  NSURLSession  session類

  NSURLSessionConfiguration 用於初始化session的配置類

  NSURLSessionTask—The base class for tasks within a session.  所有task的基類

  NSURLSessionDataTask 用來讀取url的返回內容的task類(不支持background session)

  NSURLSessionUploadTask用於上傳文件的task類

  NSURLSessionDownloadTask 用於將url下載成爲臨時文件的task類

  NSURLSessionDelegate  處理session級別的事件

  NSURLSessionTaskDelegate處理所有task級別的通用事件

  NSURLSessionDataDelegate 處理與讀取Data有關的事件

  NSURLSessionDownloadDelegate    處理與下載文件有關的事件

 

(3)使用步驟(以下載文件爲例)

  1. 創建URLSession

- (NSURLSession *)backgroundSession

{

    //Use dispatch_once_t to create only one background session. If you want more than one session, do with different identifier

    static NSURLSession *session = nil;

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:session_id];

        configuration.discretionary = YES;

        session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];

    });

    [configDict setObject:session_id forKey:@"session_id"];

    return session;

}

 

  2.創建DownloadTask

         NSURL *downloadURL = [NSURL URLWithString:@"http:// 17-45990.dmg"];

        NSURLRequest *request = [NSURLRequest requestWithURL:downloadURL];

        self.session = [self backgroundSession];

 

        self.downloadTask = [self.session downloadTaskWithRequest:request];

 

         [self.downloadTask resume];

   當創建完task,並且resume之後,任務就開始下載了

 

  3.實現下載的回調,接收事件

(1) 在需要響應回調的類裏面實現NSURLSessionDelegate、NSURLSessionTaskDelegate、NSURLSessionDownloadDelegate等協議

(2)實現以下函數:

   URLSession:downloadTask: didWriteData   獲得當前下載的數據大小及總大小

   URLSession: downloadTask: didFinishDownloadingToURL   成功下載之後調用,可以獲得臨時文件的本地地址

   URLSession: task: didCompleteWithError  文件下載失敗的回調

   URLSessionDidFinishEventsForBackgroundURLSession:  一個session結束之後,會在後臺調用

   application: performFetchWithCompletionHandler: 當App被fetch喚醒時調用

   application: handleEventsForBackgroundURLSession:completionHandler: 在這個函數中檢查是否傳輸已經完成,然後調用completionHandle來更新AppSwitcher界面

  4. 關於斷點續傳

   (1)由於下載過程是由系統在處理,即使App被殺死也不影響下載,因此App無需在斷網或者退出時記錄當前的下載位置。

   (2)當下載過程開啓後,只要系統沒有發出失敗信號,即使斷網了、系統關機了,等恢復網絡或者系統重啓之後,系統會繼續下載,此時app只需要創建與上次相同id的session,即可接收到下載進度信息。如果app收到了失敗信號,需要從nserro中通過userinfo來獲取resumedata,從而在下次恢復下載時,使用downloadTaskWithResumeData函數來創建task,這樣就可以斷點續傳,而不是用downloadTaskWithRequest來創建task,後者會開啓一個新的下載。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章