Background Service は、ユーザーインタフェースなしでバックグラウンドで長時間の操作を実行するように設計されたAndroidコンポーネントです。Activityとは異なり、アプリが最小化されたり、ユーザーが別のアプリに切り替えてもServiceは動作を続けます。Android Developers, 2026によると、Started Service、Bound Service、Foreground Serviceの3タイプのサービスがあり、それぞれ独自のライフサイクルと使用範囲を持ちます。
ポイント
Background Service (または単にService)は、Activity、BroadcastReceiver、ContentProviderと並ぶAndroidアプリケーションの4つの基本コンポーネントの1つです。Activityとは異なり、Serviceにはビジュアルインタフェースがなく、アプリケーションがフォアグラウンドにあるかどうかに関わらず続行すべき操作を実行するように設計されています。
Serviceはアプリケーションのメインスレッドで動作するため、その中でのブロッキング操作には別のスレッドを作成する必要があります。これを行わないと、システムはANR (Application Not Responding)をスローします。簡単なバックグラウンド操作には、Androidは自動的にワーカースレッドを作成するIntentServiceを提供しています。現代のプロジェクトでは、メインスレッドをブロックせずに非同期処理を行うために、Service内でCoroutineScopeを使用したKotlinコルーチンを使用することをおすすめします。
Serviceの主な目的は、音楽再生、ファイルダウンロード、ネットワークリクエストの処理、データ同期、およびユーザーがアプリを去った後も続ける必要がある他のタスクです。ただし、Android 8以降、開発者はバックグラウンド作業の制限を考慮して、サービスのタイプを意識的に選択する必要があります。
Serviceには、Activityとは異なる独自のライフサイクルがあります。onCreate、onStartCommand、onBind、onDestroyの4つのメインメソッドを含みます。メモリリークなしでバックグラウンドタスクを正しく実装するには、このサイクルを理解することが不可欠です。
onCreateメソッドは、サービスが作成される隋に一度コールされます。ここで、タイマー、データベース接続、ソケットなどのリソースが初期化されます。onStartCommandメソッドは、startServiceが呼ばれるたびにコールされ、すでに実行中のサービスにコマンドを送信できます。戻り値は、再起動時のシステムの動作を決定します。
class DownloadService : Service() {
override fun onCreate() {
super.onCreate()
initializeDownloader()
}
override fun onStartCommand(
intent: Intent?,
flags: Int,
startId: Int
): Int {
downloadFile(intent?.getStringExtra("url"))
return START_STICKY
}
override fun onBind(intent: Intent): IBinder? = null
}
onBindは、bindServiceを通じてサービスを絡った際にコールされ、クライアントとのインタラクションのためのIBinderオブジェクトを返します。このメソッドはBound Serviceでのみ使用されます。onDestroyは、サービスが硆壊される前の最終コールです。ここで、すべてのリソースが解放され、スレッドが停止され、タスクがキャンセルされます。
Androidは3タイプのServiceを提供しており、それぞれ特定のシナリオに向けて設計されています。間違ったタイプを選択すると、アプリの不安定な動作やバッテリー消耗の原因となります。
Started Serviceは、startServiceを呼ぶことで起動され、stopSelfまたはstopServiceを呼ぶまで実行されます。即時実行が必要なタスクに適しています: アナリティクスの送信、画像処理、単一ファイルのダウンロードなど。作業完了後、サービスは自己停止します。
Bound Serviceは、クライアントサーバーインタフェースを提供し、Activity、Fragmentまたは他のコンポーネントがサービスとインタラクションできるようにします。サービスは、少なくとも1つのクライアントが絡ばれている間生存します。すべてのクライアントが絡ばりを解除すると、サービスは硆壊されます。Bound Serviceは、音楽プレイヤーやナビゲーションなど、双向通信が必要なタスクに便利です。
Foreground Serviceは、ステータスバーに永続的な通知を表示するStarted Serviceです。システムはこのようなサービスをアクティブとみなし、メモリが不足していてもキルしません。Foreground Serviceは、音楽再生、オーディオ録音、位置情報の追跡、およびユーザーにとって重要な他のタスクに必須です。
| パラメータ | Started | Bound | Foreground |
|---|---|---|---|
| 起動 | startService | bindService | startForeground |
| 生存期間 | stopSelfまで | クライアントがいる間 | stopForegroundまで |
| 通知 | なし | なし | 必須 |
| キル可能 | はい | はい | いいえ |
| 例 | ダウンロード | プレイヤー | 音楽 |
Serviceの作成は、Serviceを継承するクラスを宣言し、AndroidManifest.xmlに登録することから始まります。マニフェストへの登録がなければ、システムはサービスを起動できず、startServiceの呼び出しは例外を発生させます。
// AndroidManifest.xmlへの登録
@SuppressLint("ForegroundServiceType")
class SyncService : Service() {
override fun onStartCommand(
intent: Intent?,
flags: Int,
startId: Int
): Int {
startForeground(
NOTIFICATION_ID,
createNotification()
)
performSync(intent)
return START_NOT_STICKY
}
}
ActivityまたはFragmentからサービスを起動するには、サービスクラスへの明示的な参照を持つIntentを使用します。Android 8より、Foreground ServiceにはマニフェストでFOREGROUND_SERVICEパーミッションが必要です。
// Started Serviceの起動
val intent = Intent(this, SyncService::class.java)
intent.putExtra("action", "sync")
startService(intent)
// Foreground Serviceの起動 (Android 8+)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent)
} else {
startService(intent)
}
Android 8より (API 26)、Googleはバックグラウンドサービスに厳密な制限を導入しました。バックグラウンドでのサービス起動は、例外的な場合のみ許可されます: プッシュ通知受信時、デバイスブート後、またはJobSchedulerを通じてのみです。
即時実行が必要ない長時間タスクには、WorkManagerまたはJobSchedulerを使用することをおすすめします。アプリが本当に実行中のサービスを必要とする場合、唯一の方法は、ユーザーに見える通知を伴うForeground Serviceです。バックグラウンドで通知なしでサービスを起動すると、システムに無視されます。
JobIntentServiceは、Android 5+で動作するためにサポートライブラリに登場した専門的なクラスです。IntentServiceの行動を継続しながら、JobSchedulerを通じたスケジューリングを組み合わせています。Android 8+では、JobIntentServiceは内部的にJobSchedulerを使用し、古いバージョンでは通常のServiceを使用します。これにより、アンドロイドバージョンの確認なしで、バックグラウンドタスクを統一的に処理できます。
class UploadJobService : JobIntentService() {
companion object {
private const val JOB_ID = 1000
fun enqueueWork(context: Context, work: Intent) {
enqueueWork(
context,
UploadJobService::class.java,
JOB_ID,
work
)
}
}
override fun onHandleWork(intent: Intent) {
val fileUri = intent.getStringExtra("file_uri")
// バックグラウンドスレッドで実行されます
uploadFile(fileUri)
}
}
Background Serviceでの一般的な問題は、メモリリークです。ServiceはActivityよりも長く生存できるため、Service内でのActivityへの参照は、UIコンポーネントのガベージコレクションを防げます。ServiceからUIへの通信には、WeakReference、ViewModel、またはLiveDataの使用をおすすめします。onDestroyでは、すべてのサブスクリプションをキャンセルし、スレッドを停止し、カーソルを閉じることを必ず行ってください。
Background ServiceとWorkManagerの選択はシナリオによります。Serviceは、即時に連続的に実行すべきタスクに適しています: 音楽再生、オーディオ録音、GPS追跡など。WorkManagerは、待説・保証タスクに適しています: 同期、アナリティクス送信、ログアップロードなど。WorkManagerはデバイスの再起動にも耐えますが、Serviceは耐えません。Serviceは通知でForegroundにできますが、WorkManagerはバックグラウンドで静かに動作します。実際には、開発者は両方のアプローチを組み合わせています: ユーザーにとって重要なタスクにはForeground Service、バックグラウンドのメンテナンスにはWorkManagerです。
Android 12はandroid:foregroundServiceTypeフラグを導入し、サービスの種類を指定する必要があります: dataSync, camera, connectedDevice, location, mediaPlaybackなど。タイプの指定を間違えると、起動時に例外が発生します。この実践により、Background Serviceはユーザーとシステムの両方に対してより透明になります。
マニフェストでのServiceの正しい登録には、exported属性(外部アプリへのアクセス可能性)、foregroundServiceType(Android 12+でのバックグラウンドサービス種類)、およびパーミッションが含まれます。Bound Serviceの場合、JobIntentServiceにはandroid:permission="android.permission.BIND_JOB_SERVICE"も宣言する必要があります。マニフェストへの登録がなければ、startServiceまたはbindServiceのどちらの呼び出しも例外を発生させるため、Serviceに関する問題の診断の最初の歩驢はマニフェストの確認です。
よくある質問
Serviceはアプリケーションのメインスレッド (UI Thread) で実行されます。onStartCommandまたはonHandleIntent内のブロッキング操作は、別のスレッドまたはコルーチンに移す必要があります。そうしないと、システムは5秒後にANRをスローします。ここではよくある質問の答えとして正確な値を使用しています。
IntentServiceはServiceのサブクラスで、自動的にワーカースレッドを作成し、コマンドを順番処理します。最終タスクの完了後、IntentServiceは自己停止します。Android 8以降、IntentServiceはJobIntentServiceまたはWorkManagerを推奨し、古いとみなされています。
Android 12でのバックグラウンドからのStarted Serviceの起動は禁止されています。例外は、マニフェストで宣言されたforegroundServiceTypeと有効な通知を持つForeground Serviceです。また、優先度の高いFCMメッセージを受信した後の短時間の起動も許可されています。
3つの方法があります: ローカルブロードキャストを使用するBroadcastReceiver、Handlerを介したMessenger機構、共有ViewModelを使用するMVVMアーキテクチャでのLiveData/Flowです。Bound Serviceでは、IBinderを使用してメソッドを直接呼び出します。
ServiceがSTART_STICKYフラグで起動されていた場合、メモリ不足でプロセスがキルされた後、システムがそれを再起動します。START_NOT_STICKYフラグは、システムがサービスを再起動しないことを意味します。START_REDELIVER_INTENTはSTART_STICKYに似ていますが、最終のIntentを渡します。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。