共用方式為


Xamarin.iOS 中的背景傳輸和 NSURLSession

背景傳輸是藉由設定背景 NSURLSession 和加入佇列上傳或下載工作來起始。 如果在應用程式背景、暫停或終止時完成工作,iOS 會在應用程式的AppDelegate中呼叫完成處理程式,以通知應用程式。 下圖示範此動作:

設定背景 NSURLSession 並加入佇列上傳或下載工作,以起始背景傳輸

設定背景會話

若要建立背景會話,請建立新的 NSUrlSession ,並使用 NSUrlSessionConfiguration 對象進行設定。

組態物件會決定會話可以執行的作業,以及其可執行的工作種類。 使用 方法設定的 CreateBackgroundSessionConfiguration 會話將會在不同的程式中執行,並執行任意式 (WiFi) 傳輸,以保留數據和電池使用時間。 下列程式代碼範例示範使用 CreateBackgroundSessionConfiguration 方法和唯一字串標識符,正確設定背景傳輸會話:

public partial class SimpleBackgroundTransferViewController : UIViewController
{
  NSUrlSession session = null;

  NSUrlSessionConfiguration configuration =
      NSUrlSessionConfiguration.CreateBackgroundSessionConfiguration ("com.SimpleBackgroundTransfer.BackgroundSession");
  session = NSUrlSession.FromConfiguration
      (configuration, new MySessionDelegate(), new NSOperationQueue());

}

除了組態物件之外,會話也需要會話委派和佇列。 佇列會決定工作完成的順序。 會話委派會處理傳輸程式,並處理驗證、快取和其他會話相關問題。

使用工作和委派

既然我們已設定背景會話,讓我們開始處理傳輸的工作。 我們可以使用稱為會話委派的 NSUrlSessionDelegate 實例來追蹤這些工作。 會話委派負責喚醒背景中已終止或暫停的應用程式,以處理驗證、錯誤或傳輸完成。

NSUrlSessionDelegate提供下列基本方法來檢查傳輸狀態:

  • DidFinishEventsForBackgroundSession - 此方法會在所有工作完成且傳輸完成時呼叫。
  • DidReceiveChallenge - 在需要授權時呼叫 以要求認證。
  • DidBecomeInvalidWithError - 如果 NSURLSession 變成無效,則呼叫 。

背景會話需要更特製化的委派,視執行的工作類型而定。 背景工作限制為兩種類型的工作:

  • 上傳工作 - 型 NSUrlSessionUploadTask 別的工作會使用 INSUrlSessionTaskDelegate 實作 的 INSUrlSessionDelegate介面。 這提供其他方法來追蹤上傳進度、處理 HTTP 重新導向等等。
  • 下載工作 - 類型 NSUrlSessionDownloadTask 的工作使用 INSUrlSessionDownloadDelegate 介面,其會實作 INSUrlSessionDelegateINSUrlSessionTaskDelegate。 這提供上傳工作的所有方法,以及下載特定方法來追蹤下載進度,並判斷下載工作何時繼續或完成。

下列程式代碼會定義可用來從 URL 下載影像的工作。 工作是從在背景會話上呼叫 CreateDownloadTask ,並傳入 URL 要求來啟動:

const string DownloadURLString = "http://xamarin.com/images/xamarin.png"; // or other hosted file
public NSUrlSessionDownloadTask downloadTask;

NSUrl downloadURL = NSUrl.FromString (DownloadURLString);
NSUrlRequest request = NSUrlRequest.FromUrl (downloadURL);
downloadTask = session.CreateDownloadTask (request);

接下來,建立新的會話下載委派,以追蹤此會話中的所有下載工作。 委派類別應該繼承自 NSObject ,並實作必要的介面:

public class MySessionDelegate : NSObject, INSUrlSessionDownloadDelegate
{
  public void DidWriteData (NSUrlSession session, NSUrlSessionDownloadTask downloadTask, long bytesWritten, long totalBytesWritten, long totalBytesExpectedToWrite)
  {
    Console.WriteLine (string.Format ("DownloadTask: {0}  progress: {1}", downloadTask, progress));
    InvokeOnMainThread( () => {
      // update UI with progress bar, if desired
    });
  }
  ...
}

若要了解下載工作的進度,請覆寫 DidWriteData 方法來追蹤進度,甚至更新UI。 如果應用程式位於前景,或下次開啟應用程式時,使用者將會立即顯示UI更新。

會話委派 API 提供廣泛的工具組來與工作互動。 如需會話委派方法的完整清單,請參閱 NSUrlSessionDelegate API 檔。

重要

背景會話會在背景線程上啟動,因此任何更新 UI 的呼叫都必須藉由呼叫 InvokeOnMainThread 明確地在 UI 線程上執行,以避免 iOS 終止應用程式。

處理傳輸完成

最後一個步驟是讓應用程式知道與會話相關聯的所有工作已完成,並處理新的內容。

在 中 AppDelegate,訂閱 HandleEventsForBackgroundUrl 事件。 當應用程式進入背景且傳輸會話正在執行時,會呼叫這個方法,而且系統會傳遞完成處理程式:

public System.Action backgroundSessionCompletionHandler;

public void HandleEventsForBackgroundUrl (UIApplication application, string sessionIdentifier, System.Action completionHandler)
{
  this.backgroundSessionCompletionHandler = completionHandler;
}

使用完成處理程式,讓iOS知道應用程式何時完成處理。

回想一下,會話可能會繁衍數個工作來處理傳輸。 當最後一個工作完成時,暫停或終止的應用程式會重新啟動至背景。 然後,應用程式會使用唯一的工作階段識別碼重新連線到 NSURLSession ,並在工作階段委派上呼叫 DidFinishEventsForBackgroundSession 。 此方法是應用程式處理新內容的機會,包括更新UI以反映傳輸的結果:

public void DidFinishEventsForBackgroundSession (NSUrlSession session) {
  // Handle new information, update UI, etc.
}

完成處理新內容之後,請呼叫完成處理程式,讓系統知道擷取應用程式的快照集並返回睡眠狀態是安全的:

public void DidFinishEventsForBackgroundSession (NSUrlSession session) {
  var appDelegate = UIApplication.SharedApplication.Delegate as AppDelegate;

  // Handle new information, update UI, etc.

  // call completion handler when you're done
  if (appDelegate.backgroundSessionCompletionHandler != null) {
    NSAction handler = appDelegate.backgroundSessionCompletionHandler;
    appDelegate.backgroundSessionCompletionHandler = null;
    handler.Invoke ();
  }
}

本逐步解說涵蓋在 iOS 7 和更新版本中實作背景傳輸服務的基本步驟。