Xamarin.iOS 中的背景傳輸和 NSURLSession
背景傳輸是藉由設定背景 NSURLSession
和加入佇列上傳或下載工作來起始。 如果在應用程式背景、暫停或終止時完成工作,iOS 會在應用程式的AppDelegate中呼叫完成處理程式,以通知應用程式。 下圖示範此動作:
設定背景會話
若要建立背景會話,請建立新的 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
介面,其會實作INSUrlSessionDelegate
和INSUrlSessionTaskDelegate
。 這提供上傳工作的所有方法,以及下載特定方法來追蹤下載進度,並判斷下載工作何時繼續或完成。
下列程式代碼會定義可用來從 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 和更新版本中實作背景傳輸服務的基本步驟。