バックグラウンドでの Xamarin.iOS アプリの更新
バックグラウンド更新とは、中断されているか、実行されていないアプリケーションのスリープを解除し、新しいコンテンツで更新するプロセスです。 iOS には、バックグラウンドでコンテンツを更新するための 3 つのオプションが用意されています。
- リージョンの監視と重要な場所の変更サービス - 場所に対応する API は、ユーザーの場所の変更に基づいてバックグラウンド更新をトリガーします。 これらの API は、他のオプションが利用できない場合に、場所に基づかない iOS 6 アプリケーションのコンテンツを更新するために、任意で使用できます。
- バックグラウンド フェッチ (iOS 7 以降) - 頻繁に更新される重要でないコンテンツを更新するための一時的なアプローチ。
- リモート通知 (iOS 7 以降) - プッシュ通知を受信するアプリケーションは、通知を使用してバックグラウンド コンテンツの更新をトリガーできます。 このメソッドを使用すると、散発的に更新される、時間の影響を受けやすい重要なコンテンツを使用して更新できます。
以降のセクションでは、これらのオプションの基本について説明します。
リージョンの監視と重要な場所の変更
iOS には、バックグラウンド機能を備えた 2 つの場所対応 API が用意されています。
- リージョンの監視は、境界を持つリージョンを設定し、ユーザーがリージョンに入ったときまたは出たときにデバイスのスリープ状態を解除するプロセスです。 リージョンは循環型であり、さまざまなサイズにできます。 ユーザーがリージョンの境界を越えると、通常は通知を発生させたりタスクを開始したりして、デバイスのスリープ状態が解除されてイベントが処理されます。 リージョンの監視には GPS が必要で、バッテリとデータの使用量が増加します。
- 重要な場所の変更サービスは、セルラー無線を搭載したデバイスで利用できる、よりシンプルで電力を節約できるオプションです。 重要な場所の変更をリッスンしているアプリケーションは、デバイスがセル タワーを切り替えたときに通知されます。 このサービスを使用して、中断されたアプリケーションまたは終了したアプリケーションのスリープを解除し、バックグラウンドで新しいコンテンツを確認できます。 バックグラウンド アクティビティは、バックグラウンド タスクと組み合わせて使用しない限り、約 10 秒に制限されます。
アプリケーションでは、これらの場所に対応する API を使用するために、場所の UIBackgroundMode
は必要ありません。 iOS では、ユーザーの場所の変更によってデバイスのスリープが解除されたときに実行できるタスクの種類は追跡されないため、これらの API は、iOS 6 のバックグラウンドでコンテンツを更新するための回避策を提供します。 場所ベースの API を使用してバックグラウンド更新をトリガーすると、デバイス リソースが使用されて、アプリケーションが自分の場所にアクセスする必要がある理由を理解していないユーザーが混乱する可能性があることに注意してください。 場所の API をまだ使用していないアプリケーションでバックグラウンド処理のためにリージョンの監視または重要な場所の変更を実装する場合は慎重に行います。
バックグラウンド処理に場所の監視を使用するアプリは、アプリケーションのニーズがバックグラウンドで必要なカテゴリに収まらない場合は、バックグラウンド オプションが制限されるという iOS 6 の欠陥を明らかにします。 2 つの新しい API であるバックグラウンド フェッチとリモート通知の導入により、iOS 7 以降では、より多くのアプリケーションにバックグラウンドの機会が提供されます。 次の 2 つのセクションでは、これらの新しい API について説明します。
バックグラウンド フェッチ (iOS 7 以降)
iOS 6 では、フォアグラウンドに入るアプリケーションは、新しいコンテンツを読み込むのに時間を必要とするため、ユーザーに既に表示済みのコンテンツが短時間表示されます。 バックグラウンド フェッチを使用すると、ユーザーがアプリケーションを起動する前にアプリケーションで新しいデータを読み込み、ユーザーに最新のコンテンツを提供できます。
バックグラウンド フェッチを実装するには、Info.plist を編集し、[バックグラウンド モードを有効にする] チェック ボックスと [バックグラウンド フェッチ] チェック ボックスをオンにします。
次に、AppDelegate
で、FinishedLaunching
メソッドをオーバーライドして、最小フェッチ間隔を設定します。 この例では、OS が新しいコンテンツをフェッチする頻度を決定します。
public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
{
UIApplication.SharedApplication.SetMinimumBackgroundFetchInterval (UIApplication.BackgroundFetchIntervalMinimum);
return true;
}
最後に、PerformFetch
メソッドを AppDelegate
でオーバーライドして、完了ハンドラーを渡して、フェッチを実行します。 完了ハンドラーは、UIBackgroundFetchResult
を受け取るデリゲートです。
public override void PerformFetch (UIApplication application, Action<UIBackgroundFetchResult> completionHandler)
{
// Check for new data, and display it
...
// Inform system of fetch results
completionHandler (UIBackgroundFetchResult.NewData);
}
コンテンツの更新が完了したら、適切な状態で完了ハンドラーを呼び出して OS に通知します。 iOS には、完了ハンドラーの状態に関する 3 つのオプションが用意されています。
UIBackgroundFetchResult.NewData
- 新しいコンテンツがフェッチされ、アプリケーションが更新されると呼び出されます。UIBackgroundFetchResult.NoData
- 新しいコンテンツのフェッチが完了したが、使用できるコンテンツがない場合に呼び出されます。UIBackgroundFetchResult.Failed
- エラー処理に役立ちます。これは、フェッチが完了できなかったときに呼び出されます。
バックグラウンド フェッチを使用するアプリケーションでは、バックグラウンドから UI を更新する呼び出しを行うことができます。 ユーザーがアプリを開くと、UI は最新の状態になり、新しいコンテンツが表示されます。 これにより、アプリケーションの App スイッチャー スナップショットも更新されるため、ユーザーはアプリケーションに新しいコンテンツが含まれているかどうかを確認できます。
重要
PerformFetch
が呼び出されると、アプリケーションは約 30 秒で新しいコンテンツのダウンロードを開始し、完了ハンドラー ブロックを呼び出します。 これに時間がかかりすぎる場合、アプリは終了します。 メディアやその他の大きなファイルをダウンロードするときは、バックグラウンド転送サービスでバックグラウンド フェッチを使用することを検討してください。
BackgroundFetchInterval
前述のサンプル コードでは、最小フェッチ間隔を BackgroundFetchIntervalMinimum
に設定して、新しいコンテンツをフェッチする頻度を OS で決定します。 iOS には、フェッチ間隔に次の 3 つのオプションがあります。
BackgroundFetchIntervalNever
- 新しいコンテンツをフェッチしないようシステムに指示します。 ユーザーがサインインしていない場合など、特定の状況でフェッチを無効にするには、これを使用します。 これはフェッチ間隔の既定値です。BackgroundFetchIntervalMinimum
- システムは、ユーザー パターン、バッテリ寿命、データ使用量、および他のアプリケーションのニーズに基づいてフェッチする頻度を決定します。BackgroundFetchIntervalCustom
- アプリケーションのコンテンツが更新される頻度がわかっている場合は、フェッチのたびに "スリープ" 間隔を指定できます。その間、アプリケーションは新しいコンテンツをフェッチできなくなります。 その間隔が経過すると、システムはコンテンツをフェッチするタイミングを決定します。
BackgroundFetchIntervalMinimum
と BackgroundFetchIntervalCustom
の両方が、フェッチをスケジュールするためにシステムに依存します。 この間隔は動的であり、デバイスのニーズと個々のユーザーの習慣に適応します。 たとえば、あるユーザーが毎朝アプリケーションをチェックし、別のユーザーが 1 時間おきにチェックを行う場合、iOS は、アプリケーションを開くたびに両方のユーザーのコンテンツが最新になるようにします。
バックグラウンド フェッチは、重要でないコンテンツで頻繁に更新されるアプリケーションに使用する必要があります。 重要な更新を含むアプリケーションの場合は、リモート通知を使用する必要があります。 リモート通知はバックグラウンド フェッチに基づいており、同じ完了ハンドラーを共有します。 次にリモート通知について説明します。
リモート通知 (iOS 7 以降)
プッシュ通知は、Apple Push Notification サービス (APNs) を使用してプロバイダーからデバイスに送信される JSON メッセージです。
iOS 6 では、受信プッシュ通知によって、アプリケーションで何か興味深いことが発生したことをユーザーに警告するようにシステムに通知されます。 通知をクリックすると、中断状態または終了状態からアプリケーションがプルされ、アプリケーションはコンテンツの更新を開始します。 iOS 7 以降では、通常のプッシュ通知を拡張して、アプリケーションが、ユーザーに通知する前にバックグラウンドでコンテンツを更新できるようにすることで、ユーザーがアプリケーションを開くと新しいコンテンツがすぐに表示されるようにしています。
リモート通知を実装するには、Info.plist を編集し、[バックグラウンド モードを有効にする] と [リモート通知] チェック ボックスをオンにします。
次に、プッシュ通知自体の content-available
フラグを 1 に設定します。 これにより、アプリケーションはアラートを表示する前に新しいコンテンツをフェッチするように指示されます。
'aps' {
'content-available': 1,
'alert': 'Something new has happened in your app!''
}
AppDelegate で DidReceiveRemoteNotification
メソッドをオーバーライドして、使用可能なコンテンツの通知ペイロードを確認し、適切な完了ハンドラー ブロックを呼び出します。
public override void DidReceiveRemoteNotification (UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
if([content-available]) {
// fetch content
completionHandler (UIBackgroundFetchResult.NewData);
}
}
リモート通知は、アプリケーションの機能に不可欠なコンテンツを含む頻度の低い更新に使用する必要があります。 リモート通知の詳細については、iOS のプッシュ通知に関する Xamarin のガイドを参照してください。
重要
リモート通知の更新メカニズムはバックグラウンド フェッチに基づいているため、アプリケーションは新しいコンテンツのダウンロードを開始し、通知を受信してから 30 秒以内に完了ハンドラー ブロックを呼び出す必要があります。これが実行されない場合、iOS はアプリケーションを終了します。 バックグラウンドでメディアやその他の大きなファイルをダウンロードする場合は、リモート通知とバックグラウンド転送サービスを組み合わせることを検討してください。
サイレント リモート通知
リモート通知は、更新をアプリケーションに通知し、新しいコンテンツのフェッチを開始する簡単な方法ですが、変更があったことをユーザーに通知する必要がない場合もあります。 たとえば、ユーザーがファイルに同期のフラグを設定する場合、ファイルが更新されるたびに通知する必要はありません。 ファイル同期は驚くようなイベントではなく、ユーザーの注意をすぐには必要としません。 ユーザーは、ファイルを開いたときにファイルが最新の状態になっていることを期待しているだけです。
上記のような場合、iOS ではプッシュ通知を通知なしで送信できます。つまり、アラートは送信されません。 通常の通知をサイレント通知にするには、通知ペイロードからアラートを削除するだけです。
'aps' {
'content-available': 1
}
レート制限
開発者の観点から見て、通常の通知とサイレント通知の最大の違いは、サイレント プッシュがレート制限されていることです。 APNs は、プッシュ レートが高くなりすぎると、デバイスへのサイレント プッシュの配信を遅延します。 これは、アプリケーションがサイレント通知が多すぎるデバイス リソースをドレインしないようにするためです。
ただし、APNs は、サイレント通知を通常のリモート通知またはキープアライブ応答と "ピギーバッグ" にします。 通常の通知はレート制限されないため、次の図に示すように、APNs からデバイスに保存されているサイレント通知をプッシュするために使用できます。
重要
Apple は、アプリケーションで必要な場合は常にサイレント プッシュ通知を送信して、APNs が配信をスケジュールできるようにすることを開発者に勧めています。
このセクションでは、バックグラウンドで必要なカテゴリに収まらないタスクを実行するために、バックグラウンドでコンテンツを更新するためのさまざまなオプションについて説明しました。 次に、これらの API の一部の動作を見てみましょう。