アプリからフォアグラウンド サービスを起動するには、2 つの手順が必要です。まず、
サービスを開始するには、
context.startForegroundService()を呼び出す必要があります。次に、サービスに
ServiceCompat.startForeground()を呼び出させて、フォアグラウンドサービスに
昇格させます。
前提条件
アプリがターゲットとする API レベルに応じて、アプリがフォアグラウンド サービスを起動できるタイミングに制限があります。
Android 12(API レベル 31)以降をターゲットとするアプリは、いくつかの例外を除き、アプリがバックグラウンドにあるときにフォアグラウンド サービスを開始することはできません。詳細と、このルールの 例外については、バックグラウンドからのフォアグラウンド サービスの起動に関する制限 をご覧ください。
Android 14(API レベル 34)以降をターゲットとするアプリは、フォアグラウンド サービスのタイプに適した権限をリクエストする必要があります。アプリがサービスをフォアグラウンドに昇格させようとすると、システムは適切な権限を確認し、アプリに権限がない場合は
SecurityExceptionをスローします。たとえば、locationタイプのフォアグラウンド サービスを起動しようとすると、アプリにACCESS_COARSE_LOCATION権限またはACCESS_FINE_LOCATION権限がすでに付与されていることを確認します。フォアグラウンド サービス タイプのドキュメントには、フォアグラウンド サービス タイプごとに必要な前提条件が記載されています。
サービスを起動する
フォアグラウンド サービスを起動するには、まず通常の(フォアグラウンド以外の)サービスとして起動する必要があります。
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);
コードに関する主なポイント
- このコード スニペットはサービスを起動します。ただし、サービスはまだフォアグラウンドで実行されていません。サービス自体の中で
ServiceCompat.startForeground()を呼び出して、サービスをフォアグラウンド サービスに昇格させる必要があります。
サービスをフォアグラウンドに昇格させる
サービスが実行されたら、
ServiceCompat.startForeground() を呼び出して、サービスを
フォアグラウンドで実行するようにリクエストする必要があります。通常、このメソッドはサービスの
onStartCommand() メソッドで呼び出します。
ServiceCompat.startForeground() は次のパラメータを受け取ります。
- サービス。
- ステータスバーに表示されるサービスの通知を一意に識別する正の整数。
Notificationオブジェクト自体。- サービスによって行われる作業を識別するフォアグラウンド サービスのタイプ 。
特定のユースケースに応じて、マニフェストで宣言された startForeground()
タイプに渡すフォアグラウンド サービスのタイプ。その後、サービス タイプを追加する必要がある場合は、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) } // ... } } //... }
コードに関する主なポイント
- アプリは、
CAMERA権限が必要であることをマニフェストで宣言しています。ただし、アプリは実行時に、ユーザーがその権限を付与したことを確認する必要があります。アプリに適切な権限がない場合は、ユーザーにその問題を通知する必要があります。 - フォアグラウンド サービスのタイプは、Android プラットフォームのバージョンごとに導入されています。このコードは、実行されている Android のバージョンを確認し、適切な権限をリクエストします。
- 許可されていない状況でフォアグラウンド サービスを開始しようとしている場合(たとえば、アプリがバックグラウンドにあるときにサービスをフォアグラウンドに昇格させようとしている場合)に備えて、コードは
ForegroundServiceStartNotAllowedExceptionをチェックします。