アプリからフォアグラウンド サービスを起動するには、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をチェックします(たとえば、アプリがバックグラウンドにあるときにサービスをフォアグラウンドに昇格させようとした場合など)。