フォアグラウンド サービスは、ユーザーが認識できるオペレーションを実行します。
ステータスバーに通知を表示することにより、アプリがフォアグラウンドでタスクを実行していること、それに伴いシステム リソースが消費されていることにユーザーが気付けるようにします。
フォアグラウンド サービスを使用しているアプリの例を次に示します。
- この音楽プレーヤー アプリは、フォアグラウンド サービスで音楽を再生します。通知として、いま再生中の曲が表示されます。
- このフィットネス アプリは、ユーザーからの許可を得たうえで、ユーザーのランニングをフォアグラウンド サービスで記録します。通知には、現在のフィットネス セッション中にユーザーが移動した距離が表示されます。
フォアグラウンド サービスを使用する場合は、ユーザーがアプリを直接操作していないときでも、タスクが実行されていることに気付けるようにする必要があります。アクションの重要度が低く、優先度が低い通知を使用する場合は、代わりにバックグラウンド タスクを作成します。
このドキュメントでは、フォアグラウンド サービスの使用に必要な権限と、フォアグラウンド サービスを開始してバックグラウンドから削除する方法について説明します。また、特定のユースケースをフォアグラウンド サービス タイプに関連付ける方法と、バックグラウンドで実行されているアプリからフォアグラウンド サービスを起動したときに適用されるアクセス制限についても説明します。
ユーザーがデフォルトで通知を閉じることができる
Android 13(API レベル 33)以降では、デフォルトで、ユーザーはフォアグラウンド サービスに関連付けられた通知を閉じることができます。そのためには、通知でスワイプ操作を行います。従来、フォアグラウンド サービスが停止するか、フォアグラウンドから除去されない限り、通知は閉じられません。
ユーザーが通知を閉じないようにするには、Notification.Builder
を使用して通知を作成するときに、true
を setOngoing()
メソッドに渡します。
通知をすぐに表示するサービス
フォアグラウンド サービスに次の特性の少なくとも 1 つがある場合、Android 12 以降を搭載したデバイスでも、サービスが開始されるとすぐに、関連する通知が表示されます。
- サービスがアクション ボタンを含む通知に関連付けられている。
- サービスの
foregroundServiceType
がmediaPlayback
、mediaProjection
、またはphoneCall
である。 - サービスが、通知の category 属性の定義に応じて、通話、ナビゲーション、またはメディア再生に関連するユースケースを提供している。
- サービスが、通知の設定時に
FOREGROUND_SERVICE_IMMEDIATE
をsetForegroundServiceBehavior()
に渡すことで、動作変更をオプトアウトしている。
Android 13(API レベル 33)以降では、ユーザーが通知権限を拒否しても、フォアグラウンド サービスに関連する通知がタスク マネージャーに表示されます。ただし、この通知は通知ドロワーには表示されません。
マニフェストでフォアグラウンド サービスを宣言する
アプリのマニフェストで、アプリの各フォアグラウンド サービスを <service>
要素で宣言します。サービスごとに、android:foregroundServiceType
属性を使用して、サービスが行う処理の種類を宣言します。
たとえば、アプリが音楽を再生するフォアグラウンド サービスを作成する場合は、次のようにサービスを宣言します。
<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>
<application ...>
<service
android:name=".MyMediaPlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="false">
</service>
</application>
</manifest>
サービスに複数のタイプが適用される場合は、|
演算子で区切ります。たとえば、カメラとマイクを利用するサービスは次のように宣言します。
android:foregroundServiceType="camera|microphone"
フォアグラウンド サービスの権限をリクエストする
Android 9(API レベル 28)以降をターゲットとするアプリでフォアグラウンド サービスを使用する場合、次のコード スニペットに示すように、アプリ マニフェストで FOREGROUND_SERVICE
をリクエストする必要があります。これは normal 権限であり、リクエストしたアプリに自動で付与されます。
また、アプリが API レベル 34 以降をターゲットとしている場合は、フォアグラウンド サービスが行う処理の種類に適した権限タイプをリクエストする必要があります。各フォアグラウンド サービスのタイプには、対応する権限タイプがあります。たとえば、アプリがカメラを使用するフォアグラウンド サービスを起動する場合は、FOREGROUND_SERVICE
権限と FOREGROUND_SERVICE_CAMERA
権限の両方をリクエストする必要があります。これらはすべて Normal 権限であるため、マニフェストに記載されている場合は自動的に付与されます。
<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA"/>
<application ...>
...
</application>
</manifest>
フォアグラウンド サービスの前提条件
Android 14(API レベル 34)以降では、フォアグラウンド サービスを起動すると、システムはサービスタイプに基づいて特定の前提条件を確認します。たとえば、location
タイプのフォアグラウンド サービスを起動しようとすると、アプリに ACCESS_COARSE_LOCATION
権限または ACCESS_FINE_LOCATION
権限がすでに付与されているかどうかがチェックされます。存在しない場合、システムは SecurityException
をスローします。
そのため、フォアグラウンド サービスを開始する前に、必要な前提条件が満たされていることを確認する必要があります。フォアグラウンド サービスのタイプのドキュメントに、各フォアグラウンド サービス タイプに必要な前提条件が記載されています。
フォアグラウンド サービスを開始する
サービスをフォアグラウンド サービスとして実行するようシステムにリクエストする前に、サービス自体を開始します。
Kotlin
val intent = Intent(...) // Build the intent for the service context.startForegroundService(intent)
Java
Context context = getApplicationContext(); Intent intent = new Intent(...); // Build the intent for the service context.startForegroundService(intent);
サービス内(通常は onStartCommand()
内)で、サービスをフォアグラウンドで実行するようリクエストできます。これを行うには、ServiceCompat.startForeground()
を呼び出します(androidx-core 1.12 以降で利用可能)。このメソッドが取るパラメータは次のとおりです。
- サービス
- ステータスバーの通知を一意に識別する正の整数
Notification
オブジェクト自体- サービスが行う処理を識別するフォアグラウンド サービスタイプ
これらのタイプは、特定のユースケースに応じて、マニフェストで宣言されたタイプのサブセットである場合があります。サービスタイプをさらに追加する必要がある場合は、startForeground()
を再度呼び出すことができます。
たとえば、フィットネス アプリが、常に location
情報を必要とするランニング トラッカー サービスを実行しているが、メディアの再生が必要になる場合とそうでない場合があります。マニフェストで location
と mediaPlayback
の両方を宣言する必要があります。ユーザーがランニングを開始し、位置情報の追跡のみを希望する場合、アプリは startForeground()
を呼び出して ACCESS_FINE_LOCATION
権限のみを渡す必要があります。次に、ユーザーが音声の再生を開始する場合は、startForeground()
を再度呼び出して、すべてのフォアグラウンド サービス タイプのビット単位の組み合わせ(この場合は ACCESS_FINE_LOCATION|FOREGROUND_SERVICE_MEDIA_PLAYBACK
)を渡します。
カメラのフォアグラウンド サービスを起動する例を次に示します。
Kotlin
class MyCameraService: Service() { private fun startForeground() { // Before starting the service as foreground check that the app has the // appropriate runtime permissions. In this case, verify that the user has // granted the CAMERA permission. val cameraPermission = PermissionChecker.checkSelfPermission(this, Manifest.permission.CAMERA) if (cameraPermission != PermissionChecker.PERMISSION_GRANTED) { // Without camera permissions the service cannot run in the foreground // Consider informing user or updating your app UI if visible. stopSelf() return } try { val notification = NotificationCompat.Builder(this, "CHANNEL_ID") // Create the notification to display while the service is running .build() ServiceCompat.startForeground( /* service = */ this, /* id = */ 100, // Cannot be 0 /* notification = */ notification, /* foregroundServiceType = */ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA } else { 0 }, ) } catch (e: Exception) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && e is ForegroundServiceStartNotAllowedException) { // App not in a valid state to start foreground service // (e.g. started from bg) } // ... } } }
Java
public class MyCameraService extends Service { private void startForeground() { // Before starting the service as foreground check that the app has the // appropriate runtime permissions. In this case, verify that the user // has granted the CAMERA permission. int cameraPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA); if (cameraPermission == PackageManager.PERMISSION_DENIED) { // Without camera permissions the service cannot run in the // foreground. Consider informing user or updating your app UI if // visible. stopSelf(); return; } try { Notification notification = new NotificationCompat.Builder(this, "CHANNEL_ID") // Create the notification to display while the service // is running .build(); int type = 0; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { type = ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA; } ServiceCompat.startForeground( /* service = */ this, /* id = */ 100, // Cannot be 0 /* notification = */ notification, /* foregroundServiceType = */ type ); } catch (Exception e) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && e instanceof ForegroundServiceStartNotAllowedException ) { // App not in a valid state to start foreground service // (e.g started from bg) } // ... } } //... }
フォアグラウンドからサービスを削除する
サービスをフォアグラウンドから除去するには、stopForeground()
を呼び出します。このメソッドは、ステータスバーの通知も削除するかどうかを示すブール値を受け取ります。サービスは引き続き実行されます。
サービスがフォアグラウンドで実行中に停止すると、その通知は削除されます。
フォアグラウンド サービスを実行しているアプリのユーザーが開始した停止を処理する
Android 13(API レベル 33)以降では、アプリのターゲット SDK バージョンにかかわらず、ユーザーは通知ドロワーからワークフローを完了し、フォアグラウンド サービスが進行中のアプリを停止できます。タスク マネージャーと呼ばれるこのアフォーダンスは、現在フォアグラウンド サービスを実行しているアプリのリストを表示します。
このリストには、[有効なアプリ] というラベルが付いています。各アプリの横に [停止] ボタンがあります。図 1 は、Android 13 を搭載したデバイス上のタスク マネージャーのワークフローを示しています。
タスク マネージャーでユーザーがアプリの横の [停止] ボタンを押すと、次のアクションが発生します。
- システムがメモリからアプリを削除します。そのため、実行中のフォアグラウンド サービスだけでなく、アプリ全体が停止します。
- システムはアプリのアクティビティのバックスタックを削除します。
- メディアの再生が停止します。
- フォアグラウンド サービスに関連付けられた通知が削除されます。
- アプリは履歴に残ります。
- スケジュールされたジョブは、スケジュールされた時刻に実行されます。
- アラームは、設定した時刻または時間帯に鳴ります。
ユーザーがアプリを停止している間または停止した後でアプリが想定どおりに動作するかどうかをテストするには、ターミナル ウィンドウで次の ADB コマンドを実行します。
adb shell cmd activity stop-app PACKAGE_NAME
除外
特定のタイプのアプリには、以下のセクションで説明するいくつかのレベルの除外が適用されます。
除外は、プロセス単位ではなくアプリ単位で適用されます。アプリ内の 1 つのプロセスが除外されると、そのアプリ内の他のプロセスもすべて除外されます。
タスク マネージャーの表示対象からの除外
以下のアプリは、タスク マネージャーに一切表示されることなく、フォアグラウンド サービスを実行できます。
- システムレベルのアプリ
- 緊急情報サービスアプリ(つまり、
ROLE_EMERGENCY
ロールを持つアプリ) - デモモードのデバイス
ユーザーによる停止対象からの除外
以下のタイプのアプリがフォアグラウンド サービスを実行している場合、それらはタスク マネージャーに表示されますが、アプリ名の横に、ユーザーがタップできる [停止] ボタンは表示されません。
- デバイス所有者アプリ
- プロファイル所有者アプリ
- 永続的なアプリ
ROLE_DIALER
ロールを持つアプリ
フォアグラウンド サービスの代わりに専用の API を使用する
多くのユースケースでは、フォアグラウンド サービスを使用する代わりに、プラットフォーム API または Jetpack API を使用して処理を行うことができます。適切な専用 API がある場合は、ほとんどの場合、フォアグラウンド サービスを使用する代わりに API を使用する必要があります。専用に構築された API には、通常、ユースケース固有の追加機能が用意されています。これらの機能は、自分で構築する必要がありました。たとえば、 Bubbles API は、チャット バブル機能を実装する必要があるメッセージ アプリの複雑な UI ロジックを処理します。
フォアグラウンド サービスのタイプのドキュメントには、フォアグラウンド サービスの代わりに使用できる代替手段が記載されています。
バックグラウンドからフォアグラウンド サービスを開始する場合の制限
Android 12 以降をターゲットとするアプリは、少数の特殊なケースを除き、バックグラウンドで動作しているときにフォアグラウンド サービスを起動できません。アプリがバックグラウンドで動作しているときにフォアグラウンド サービスを起動しようとすると、そのフォアグラウンド サービスが例外ケースのいずれかに該当しない限り、システムは ForegroundServiceStartNotAllowedException
をスローします。
また、使用中の権限(ボディセンサー、カメラ、マイク、位置情報の権限など)が必要なフォアグラウンド サービスをアプリが起動する場合、アプリがバックグラウンド起動制限の例外のいずれかに該当する場合でも、アプリがバックグラウンドにある間はサービスを作成できません。その理由については、使用中の権限が必要なフォアグラウンド サービスの起動に関する制限のセクションで説明します。
バックグラウンドでの起動の制限の適用除外
以下の状況では、アプリがバックグラウンドで動作しているときでも、フォアグラウンド サービスを起動できます。
- アプリがユーザーに表示された状態(アクティビティなど)から遷移する。
- アプリがバックグラウンドからアクティビティを開始できる。ただし、既存のタスクのバックスタックにアプリのアクティビティがある場合は除きます。
アプリが Firebase Cloud Messaging を使用して優先度の高いメッセージを受信する。
ユーザーがアプリに関連する UI 要素でアクションを実行する。たとえば、バブル、通知、ウィジェット、またはアクティビティを操作する。
アプリが正確なアラームを呼び出して、ユーザーがリクエストしたアクションを完了します。
アプリがデバイスの現在の入力方法である。
アプリがジオフェンスまたはアクティビティ遷移の検出に関連するイベントを受信する。
デバイスが再起動して、ブロードキャスト レシーバで
ACTION_BOOT_COMPLETED
、ACTION_LOCKED_BOOT_COMPLETED
、またはACTION_MY_PACKAGE_REPLACED
のインテント アクションを受信した後。アプリがブロードキャスト レシーバで
ACTION_TIMEZONE_CHANGED
、ACTION_TIME_CHANGED
、またはACTION_LOCALE_CHANGED
のインテント アクションを受信する。アプリは
NfcService
からACTION_TRANSACTION_DETECTED
イベントを受信します。アプリがコンパニオン デバイス マネージャーを使用していて、
REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND
権限またはREQUEST_COMPANION_RUN_IN_BACKGROUND
権限を宣言している。可能な限りREQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND
を使用してください。ユーザーがアプリの電池の最適化をオフにする。
アプリに
SYSTEM_ALERT_WINDOW
権限が付与されている。注: Android 15 以降をターゲットとするアプリは、SYSTEM_ALERT_WINDOW
権限を持ち、現在オーバーレイ ウィンドウが表示されている必要があります。
使用中の権限が必要なフォアグラウンド サービスの起動に関する制限
Android 14(API レベル 34)以降では、使用中の権限が必要なフォアグラウンド サービスを開始する場合に注意すべき特別な状況があります。
アプリが Android 14 以降をターゲットとしている場合、オペレーティング システムはフォアグラウンド サービスを作成するときに、アプリにそのサービス タイプに適したすべての権限があることを確認します。たとえば、microphone タイプのフォアグラウンド サービスを作成すると、オペレーティング システムは、アプリに現在 RECORD_AUDIO
権限が付与されていることを確認します。この権限がない場合、システムは SecurityException
をスローします。
使用中の権限の場合、問題が発生する可能性があります。アプリに「使用中」権限が付与されている場合、その権限はフォアグラウンドで実行されている間のみ有効です。つまり、アプリがバックグラウンドにあり、カメラ、位置情報、マイクタイプのフォアグラウンド サービスを作成しようとすると、アプリに必要な権限が現在付与されていないことがシステムで検出され、SecurityException
がスローされます。
同様に、アプリがバックグラウンドにあり、BODY_SENSORS
権限が必要なヘルスサービスを作成した場合、アプリには現在その権限がないため、システムは例外をスローします。(これは、ACTIVITY_RECOGNITION
など、異なる権限が必要なヘルスサービスには適用されません)。PermissionChecker.checkSelfPermission()
を呼び出しても、この問題は回避されません。アプリに使用中の権限があり、checkSelfPermission()
を呼び出してその権限があるかどうかを確認すると、アプリがバックグラウンドにある場合でも、メソッドは PERMISSION_GRANTED
を返します。メソッドが PERMISSION_GRANTED
を返すと、「アプリはアプリの使用中にこの権限を持ちます」と表示されます。
そのため、フォアグラウンド サービスで使用中の権限が必要な場合は、サービスが定義された例外のいずれかに該当しない限り、アプリにアクティビティが表示されている間に Context.startForegroundService()
または Context.bindService()
を呼び出す必要があります。
使用中の権限の制限の免除
アプリが バックグラウンドで実行されているときにフォアグラウンド サービスが開始された場合でも、アプリがフォアグラウンドで実行されている間(「使用中」)に、位置情報、カメラ、マイクの情報にアクセスできる場合があります。
同様の状況で、サービスが location
のフォアグラウンド サービスのタイプを申告し、ACCESS_BACKGROUND_LOCATION
権限を持つアプリによってサービスが開始された場合、このサービスは、アプリがバックグラウンドで実行されている場合でも、常に位置情報にアクセスできます。
これらの状況は次のとおりです。
- システム コンポーネントがサービスを開始します。
- サービスは、アプリ ウィジェットを操作することで開始されます。
- 通知を操作することでサービスが開始される。
- 表示されている別のアプリから送信された
PendingIntent
としてサービスが開始される。 - デバイス所有者モードで実行されている Device Policy Controller であるアプリによってサービスが開始される。
VoiceInteractionService
を提供するアプリによってサービスが開始される。START_ACTIVITIES_FROM_BACKGROUND
特権を持つアプリによってサービスが開始される。
アプリで影響を受けるサービスを特定する
アプリをテストするとき、フォアグラウンド サービスを開始します。開始されたサービスが、位置情報、マイク、カメラに対するアクセスを制限されている場合は、次のメッセージが Logcat に表示されます。
Foreground service started from background can not have \ location/camera/microphone access: service SERVICE_NAME