アプリからフォアグラウンド サービスを起動するには、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
をチェックします。