アプリでは、一度に複数の処理を行う必要があることがよくあります。Android API には、これを実現するためのさまざまな方法が用意されています。適切なオプションを選択することは非常に重要です。ある状況では適切なオプションが、別の状況では不適切な場合があります。間違った API を選択すると、アプリのパフォーマンスやリソース効率が低下し、バッテリーが消耗して、ユーザーのデバイス全体のパフォーマンスが低下する可能性があります。場合によっては、間違ったアプローチを選択すると、アプリが Google Play ストアに掲載されなくなる可能性があります。
このドキュメントでは、利用可能なさまざまなオプションについて説明し、状況に適したオプションを選択できるようにします。
用語
バックグラウンド タスクに関連する重要な用語の中には、複数の矛盾した方法で使用されるものがあります。そのため、用語を定義することが重要です。
アプリがバックグラウンドで実行されている場合、システムはアプリにさまざまな制限を適用します。(たとえば、ほとんどの場合、バックグラウンドのアプリはフォアグラウンド サービスを起動できません)。
このドキュメントでは、アプリがメイン ワークフローの外部で行うオペレーションを「タスク」と呼びます。理解を一致させるため、タスクの種類を 3 つの主なカテゴリに分類しました。非同期処理、タスク スケジューリング API、フォアグラウンド サービスです。
適切なオプションの選択
ほとんどの場合、タスクが該当するカテゴリ(非同期処理、タスク スケジューリング API、フォアグラウンド サービス)を特定することで、タスクに使用する適切な API を特定できます。
それでも判断に迷う場合は、Google が提供するフローチャートを使用すると、より詳細な判断が可能です。これらの各オプションについては、このドキュメントの後半で詳しく説明します。
バックグラウンド タスクで考慮すべき主なシナリオは次の 2 つです。
この 2 つのシナリオには、それぞれ独自のディシジョン ツリーがあります。
非同期処理
多くの場合、アプリはフォアグラウンドで実行されている間に同時実行オペレーションを行うだけで済みます。たとえば、アプリで時間のかかる計算を行う必要があるとします。UI スレッドで計算を行うと、計算が完了するまでユーザーはアプリを操作できなくなります。これにより、ANR エラーが発生する可能性があります。このような場合、アプリは非同期処理オプションを使用する必要があります。
一般的な非同期処理のオプションには、Kotlin コルーチンや Java スレッドなどがあります。詳細については、非同期処理のドキュメントをご覧ください。バックグラウンド タスク API とは異なり、アプリが有効なライフサイクル ステージにない場合(アプリがフォアグラウンドから離れた場合など)、非同期処理が完了する保証はありません。
タスク スケジューリング API
タスク スケジューリング API は、ユーザーがアプリを離れても継続する必要があるタスクを実行する必要がある場合に、より柔軟なオプションとなります。ほとんどの場合、バックグラウンド タスクを実行するための最適なオプションは WorkManager を使用することですが、場合によっては、プラットフォームの JobScheduler API を使用することが適切なこともあります。
WorkManager は、必要に応じて単純なジョブや複雑なジョブを設定できる強力なライブラリです。WorkManager を使用すると、特定の時間に実行するタスクをスケジュールしたり、タスクを実行する条件を指定したりできます。タスクのチェーンを設定して、各タスクを順番に実行し、結果を次のタスクに渡すこともできます。利用可能なすべてのオプションについては、WorkManager の機能リストをご覧ください。
バックグラウンド タスクの一般的なシナリオには、次のようなものがあります。
- サーバーから定期的にデータを取得する
- センサーデータ(歩数計データなど)の取得
- 定期的な位置情報の取得(Android 10 以降では
ACCESS_BACKGROUND_LOCATION権限が付与されている必要があります) - コンテンツ トリガーに基づいてコンテンツをアップロードする(カメラで撮影した写真など)
フォアグラウンド サービス
フォアグラウンド サービスは、中断すべきでないタスクをすぐに実行するための強力な方法です。ただし、フォアグラウンド サービスはデバイスに大きな負荷をかける可能性があり、プライバシーやセキュリティに影響を及ぼすこともあります。そのため、アプリがフォアグラウンド サービスを使用する方法とタイミングには、システムによって多くの制限が課されます。たとえば、フォアグラウンド サービスはユーザーに認識される必要があり、ほとんどの場合、アプリがバックグラウンドにあるときにフォアグラウンド サービスを起動することはできません。詳細については、フォアグラウンド サービスのドキュメントをご覧ください。
フォアグラウンド サービスを作成する方法は 2 つあります。独自の Service を宣言し、Service.startForeground() を呼び出して、サービスがフォアグラウンド サービスであることを指定できます。または、長時間実行ワーカーのサポートで説明されているように、WorkManager を使用してフォアグラウンド サービスを作成することもできます。ただし、WorkManager によって作成されたフォアグラウンド サービスは、他のフォアグラウンド サービスと同じ制限に従う必要があります。WorkManager は、フォアグラウンド サービスの作成を簡素化する便利な API を提供しているだけです。
代替 API
システムには、より具体的なユースケースでより優れたパフォーマンスを発揮するように設計された代替 API が用意されています。ユースケースに代替 API が存在する場合は、フォアグラウンド サービスの代わりにその API を使用することをおすすめします。これにより、アプリのパフォーマンスが向上します。フォアグラウンド サービスのタイプのドキュメントには、特定のフォアグラウンド サービス タイプの代わりに使用できる適切な代替 API が記載されています。
代替 API を使用する最も一般的なシナリオは次のとおりです。
- データ同期フォアグラウンド サービスを作成する代わりに、ユーザーが開始するデータ転送を使用して、大規模なダウンロードまたはアップロードを行う
- Bluetooth のペア設定とデータ転送に、接続済みデバイスのフォアグラウンド サービスではなく、コンパニオン デバイス マネージャーを使用する
- メディア再生フォアグラウンド サービスを作成する代わりに、ピクチャー イン ピクチャー モードを使用して動画を再生する
ユーザーが開始したタスク
アプリがバックグラウンド タスクを実行する必要があり、アプリが表示されている間にユーザーがオペレーションを開始する場合は、次の質問に答えて適切なアプローチを見つけてください。
アプリがバックグラウンドにある間もタスクを実行し続ける必要があるか。
アプリがバックグラウンドにあるときにタスクを実行し続ける必要がない場合は、非同期処理を使用する必要があります。非同期処理を行うには、さまざまな方法があります。重要なのは、アプリがバックグラウンドに移行すると、これらのオプションはすべて動作を停止するということです。(アプリがシャットダウンされた場合も停止します)。たとえば、ソーシャル メディア アプリはコンテンツ フィードを更新する必要があるかもしれませんが、ユーザーが画面を離れた場合は、オペレーションを完了する必要はありません。
タスクが延期または中断された場合、ユーザー エクスペリエンスに悪影響を及ぼすか?
タスクが延期またはキャンセルされた場合に、ユーザー エクスペリエンスが損なわれるかどうかを考慮することが重要です。たとえば、アプリがアセットを更新する必要がある場合、ユーザーは、その処理がすぐに実行されるか、デバイスの充電中に夜間に実行されるかに気付かない可能性があります。このような場合は、バックグラウンド処理のオプションを使用する必要があります。
短時間で完了する重要なタスクですか?
タスクを遅らせることができず、すぐに完了する場合は、タイプ shortService のフォアグラウンド サービスを使用できます。これらのサービスは、他のフォアグラウンド サービスよりも簡単に作成でき、必要な権限も少なくなります。ただし、短いサービスは 3 分以内に完了する必要があります。
この目的専用の代替 API はありますか?
タスクがユーザーに表示される場合は、フォアグラウンド サービスを使用するのが適切な解決策となる可能性があります。これらのサービスは、開始されると継続的に実行されるため、タスクを中断するとユーザー エクスペリエンスが低下する場合に適しています。たとえば、ワークアウト記録アプリは、位置情報センサーを使用して、ユーザーがジョギング ルートを地図上に記録できるようにします。バックグラウンド処理オプションでは、タスクが一時停止するとトラッキングがすぐに停止するため、この処理は行いません。このような状況では、フォアグラウンド サービスが最も適しています。
ただし、フォアグラウンド サービスはデバイスのリソースを大量に使用する可能性があるため、システムは、フォアグラウンド サービスを使用できるタイミングと方法に多くの制限を設けています。多くの場合、フォアグラウンド サービスを使用する代わりに、代替 API を使用して、より簡単にジョブを処理できます。たとえば、ユーザーが特定の場所に到着したときにアプリがアクションを実行する必要がある場合は、フォアグラウンド サービスでユーザーの位置情報を追跡するのではなく、ジオフェンス API を使用することをおすすめします。
イベントに対応するタスク
アプリは、次のようなトリガーに応じてバックグラウンド処理を行う必要がある場合があります。
- ブロードキャスト メッセージ
- Firebase Cloud Messaging(FCM)メッセージ
- アプリによって設定されたアラーム
これは、外部トリガー(FCM メッセージなど)の場合もあれば、アプリ自体によって設定されたアラームに応答する場合もあります。たとえば、ゲームは、一部のアセットを更新するように指示する FCM メッセージを受信することがあります。
タスクが数秒で完了することが確実な場合は、非同期処理を使用してタスクを実行します。アプリがバックグラウンドで動作している場合でも、システムはアプリがこうしたタスクを実行できるように数秒間待機します。
タスクに数秒以上かかる場合は、フォアグラウンド サービスを開始してタスクを処理するのが適切な場合があります。実際、アプリが現在バックグラウンドにある場合でも、タスクがユーザーによってトリガーされ、承認済みのバックグラウンド開始制限の除外のいずれかに該当する場合は、フォアグラウンド サービスの開始が許可されることがあります。たとえば、アプリが優先度の高い FCM メッセージを受信した場合、アプリがバックグラウンドにあってもフォアグラウンド サービスを開始できます。
タスクに数秒以上かかる場合は、タスク スケジューリング API を使用します。