Android 12 をターゲットとするアプリは、バックグラウンドで動作しているとき、少数の特殊なケースを除いて、フォアグラウンド サービスを起動できなくなりました。アプリがバックグラウンドで動作しているときにフォアグラウンド サービスを起動しようとすると、そのフォアグラウンド サービスが例外ケースのいずれかに該当しない限り、システムは ForegroundServiceStartNotAllowedException
をスローします。
推奨されるフォアグラウンド サービスの代替策: WorkManager
アプリがこの変更の影響を受ける場合は、WorkManager を使用する方法に移行してください。WorkManager は、優先度の高いバックグラウンド タスクを開始するための推奨ソリューションです。
WorkManager 2.7.0 以降では、アプリは setExpedited()
を呼び出して、Worker
が優先ジョブを使用する旨宣言できます。この新しい API は、Android 12 で実行されたときは優先ジョブを使用し、以前のバージョンの Android ではフォアグラウンド サービスを使用して下位互換性を提供しています。
次のコード スニペットは、setExpedited()
メソッドの使用方法の例を示しています。
Kotlin
OneTimeWorkRequestBuilder<T>().apply { setInputData(inputData) setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) }.build()
Java
OneTimeWorkRequest request = new OneTimeWorkRequestBuilder<T>() .setInputData(inputData) .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) .build();
CoroutineWorker.setForeground()
メソッドと ListenableWorker.setForegroundAsync()
メソッドはフォアグラウンド サービスによってサポートされるため、これらのメソッドには同じフォアグラウンド サービスの起動に関する制限と除外が適用されます。状況によって API を使用することはできますが、この制限によりアプリがフォアグラウンド サービスを起動できない場合に、例外を処理できるようにしておく必要があります。より一貫性のあるエクスペリエンスを実現するには、setExpedited()
を使用します。
WorkManager 2.7.0 が優先ジョブを使用する方法の詳細な例については、GitHub の WorkManagerSample をご覧ください。
優先ジョブ
Android 12 の新機能である優先ジョブを使用すると、アプリが処理時間の短い重要なタスクを実行している間、システムはリソースへのアクセスをより適切に制御できます。優先ジョブは、フォアグラウンド サービスと標準の JobScheduler
ジョブの中間的な性質を持っています。
- 優先ジョブは、数分で完了するタスクを対象にしています。アプリに十分な割り当てがない限り、3 分以上実行されている優先ジョブはシステムによって停止される場合があります。
- 優先ジョブは、一部の電源管理に関する制限(バッテリー セーバーや Doze など)による影響をそれほど受けません。
- システムの現在のワークロードが許容すれば、優先ジョブはすぐに実行されます。
優先ジョブは遅延する可能性がある
システムは、指定された優先ジョブが呼び出されると、できる限り速やかに実行しようと試みます。ただし、他のタイプのジョブと同様に、システムによって新しい優先ジョブの開始が遅延されることがあります。たとえば、次のような場合です。
- システム負荷が高すぎる。これは実行中のジョブが多すぎる場合や、システムに十分なメモリがないときに発生する可能性があります。
- 優先ジョブの割り当て上限を超えている。優先ジョブでは、アプリ スタンバイ バケットに基づく割り当てシステムにより、ローリング時間枠内の最大実行時間が制限されます。優先ジョブに使用される割り当ては、他のタイプのバックグラウンド ジョブに使用される割り当てよりも厳格に制限されます。
Alarm Manager API への影響
一般に、Android 12 をターゲットとするアプリでは、アラームを使用してフォアグラウンド サービスを起動することはできません。
ただし、アプリで時間的制約のあるアラームやリマインダーをユーザーに送信する必要があるユースケースに対応できるように、正確なアラームがトリガーされたときにフォアグラウンド サービスを起動することは可能です。正確なアラームを設定するには、アプリで SCHEDULE_EXACT_ALARM
権限を宣言する必要があります。
詳しくは、正確なアラームの権限をご覧ください。
バックグラウンドからフォアグラウンド サービスを起動することが許可されるケース
以下の状況では、アプリがバックグラウンドで動作しているときでも、フォアグラウンド サービスを起動できます。
- アプリがユーザーに表示された状態(アクティビティなど)から遷移する。
- アプリがバックグラウンドからアクティビティを開始できる。ただし、既存のタスクのバックスタックにアプリのアクティビティがある場合は除きます。
- アプリが Firebase Cloud Messaging を使用して優先度の高いメッセージを受信する。
- ユーザーがアプリに関連する UI 要素でアクションを実行する。たとえば、バブル、通知、ウィジェット、またはアクティビティを操作する。
- アプリがジオフェンスまたはアクティビティ遷移の検出に関連するイベントを受信する。
- デバイスが再起動して、ブロードキャスト レシーバで
ACTION_BOOT_COMPLETED
、ACTION_LOCKED_BOOT_COMPLETED
、またはACTION_MY_PACKAGE_REPLACED
のインテント アクションを受信した後。 - アプリがブロードキャスト レシーバで
ACTION_TIMEZONE_CHANGED
、ACTION_TIME_CHANGED
、またはACTION_LOCALE_CHANGED
のインテント アクションを受信する。 - アプリが
BLUETOOTH_CONNECT
権限またはBLUETOOTH_SCAN
権限が必要な Bluetooth ブロードキャストを受信する。 - アプリがデバイス所有者やプロファイル所有者など、特定のシステムロールまたは権限を持っている。
アプリがコンパニオン デバイス マネージャーを使用している。
コンパニオン デバイスが近くにあるときに常にアプリを復帰させるため、Android 12 にコンパニオン デバイス サービスを実装している。
システムが「固定」フォアグラウンド サービスを再起動する。フォアグラウンド サービスを固定するには、
onStartCommand()
からSTART_STICKY
またはSTART_REDELIVER_INTENT
を返します。ユーザーがアプリの電池の最適化をオフにする。このオプションをユーザーが見つけられるようにするには、システム設定の [アプリ情報] ページにユーザーを誘導します。そのためには、
ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS
インテント アクションを含むインテントを呼び出します。