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
が無効になった場合に呼び出されます。
バックグラウンド セッションでは、実行されているタスクの種類に応じて、より特殊なデリゲートが必要になります。 バックグラウンド セッションは、次の 2 種類のタスクに制限されます。
- "アップロード タスク" - 種類が
NSUrlSessionUploadTask
のタスクは、INSUrlSessionDelegate
を実装するINSUrlSessionTaskDelegate
インターフェイスを使用します。 これにより、アップロードの進行状況の追跡や HTTP リダイレクトの処理などを行うための追加のメソッドが提供されます。 - "ダウンロード タスク" - 種類が
NSUrlSessionDownloadTask
のタスクは、INSUrlSessionDelegate
とINSUrlSessionTaskDelegate
を実装するINSUrlSessionDownloadDelegate
インターフェイスを使用します。 これにより、アップロード タスクのすべてのメソッドに加えて、ダウンロードの進行状況を追跡し、ダウンロード タスクがいつ再開または完了したかを判断するダウンロード固有メソッドが提供されます。
次のコードでは、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 を更新する呼び出しは、UI スレッドで明示的に実行する必要があります。そのためには、iOS によってアプリが終了されないように、InvokeOnMainThread
を呼び出します。
転送完了の処理
最後の手順では、セッションに関連付けられているすべてのタスクが完了したことをアプリケーションに通知し、新しいコンテンツを処理します。
AppDelegate
で、HandleEventsForBackgroundUrl
イベントをサブスクライブします。 アプリケーションがバックグラウンドに切り替わり、転送セッションが実行中の場合、このメソッドが呼び出され、システムから完了ハンドラーが渡されます。
public System.Action backgroundSessionCompletionHandler;
public void HandleEventsForBackgroundUrl (UIApplication application, string sessionIdentifier, System.Action completionHandler)
{
this.backgroundSessionCompletionHandler = completionHandler;
}
完了ハンドラーを使用して、アプリケーションの処理が完了したときに iOS に通知します。
1 つのセッションで複数のタスクを生成して転送を処理できることを思い出してください。 最後のタスクが完了すると、中断または終了されたアプリケーションがバックグラウンドで再起動されます。 次に、アプリケーションは一意のセッション識別子を使用して 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 以降でバックグラウンド転送サービスを実装するための基本的な手順について説明しました。