導入:Foreground Serviceは「最後の砦」
Androidでバックグラウンド処理を実装していると、最終的に行き着くのが Foreground Service です。
「これなら確実に落ちないはず」
「とりあえず Foreground にすればいい」
そう思って実装した結果、起動しない・即死する・ストア審査に引っかかるという事故は今でも頻発します。
Foreground Service は強力ですが、使い方を間違えると最も壊れやすい仕組みでもあります。
この記事では、Foreground Service の要件と通知設計を整理し、「落ちない実装」をどう作るかを解説します。
先に結論です。
- Foreground Service は「常駐用」ではない
- 通知設計が実装の半分を占める
- 要件違反は即クラッシュ or 即制限対象
Foreground Serviceとは何か
Foreground Service は、ユーザーに「今この処理が動いている」と明示した上で実行される Serviceです。
通常のバックグラウンド Service と違い、
- 常に通知を表示する義務がある
- ユーザーに可視であることが前提
- OSから「重要な処理」として扱われる
という強い制約と引き換えに、実行継続が保証される仕組みです。
まず理解すべき大前提
Foreground Service は、「バックグラウンド制限の抜け道」ではありません。
- 常駐用途は禁止
- 目的が不明確な実行は禁止
- ユーザーに説明できない処理は禁止
ここを勘違いすると、設計段階で詰みます。
Foreground Service の要件
最低限、次のルールを守る必要があります。
- 起動後、短時間以内に startForeground() を呼ぶ
- 常に通知を表示し続ける
- 処理の内容がユーザーに説明可能である
よくある死亡パターン
- startForeground を呼ぶ前に重い処理をしている
- 通知作成に失敗して例外が出る
- 通知チャンネル未作成でクラッシュ
これらは即クラッシュ案件です。
基本実装の形
Service クラス
class SampleForegroundService : Service() {
override fun onCreate() {
super.onCreate()
startInForeground()
}
private fun startInForeground() {
val notification = createNotification()
startForeground(1, notification)
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
// 実処理
return START_NOT_STICKY
}
override fun onBind(intent: Intent?): IBinder? = null
}
通知の作成
private fun createNotification(): Notification {
val channelId = "foreground_service_channel"
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
channelId,
"Foreground Service",
NotificationManager.IMPORTANCE_LOW
)
manager.createNotificationChannel(channel)
}
return NotificationCompat.Builder(this, channelId)
.setContentTitle("処理実行中")
.setContentText("バックグラウンド処理を実行しています")
.setSmallIcon(R.drawable.ic_notification)
.build()
}
通知が作れなかった瞬間に、このServiceは死にます。
通知設計がすべてを決める
Foreground Service の実装で一番重要なのは、
Service本体ではなく通知設計です。
通知に求められる条件
- 何の処理か分かる
- ユーザーが納得できる
- 消せない理由が説明できる
「とりあえず表示しておく通知」は、ほぼ確実にNG判定されます。
用途別・正しい使いどころ
使ってよい例
- 音楽再生
- ナビゲーション
- 通話・録音
- ファイル転送の進捗表示
やってはいけない例
- 定期同期の常駐化
- ユーザーに見えない裏処理
- WorkManager の代わり
WorkManager との役割分担
「落ちないバックグラウンド処理」という意味では、
WorkManager の方が圧倒的に安全です。
Foreground Service は、
「ユーザーに見せる必要があるリアルタイム処理」専用と考えるのが正解です。
Androidバージョン差分の罠
- 起動制限の強化
- 通知権限の影響
- バックグラウンド起動制限
「昔動いていたコード」がそのまま通る保証はありません。
テストで必ず確認すべきポイント
- 起動直後に落ちないか
- 通知が必ず表示されるか
- 通知を消せないか
- 画面回転・プロセスキル後の挙動
よくあるアンチパターン
- とりあえず Foreground にする
- 通知をダミー扱いする
- 常駐前提で設計する
まとめ
- Foreground Service は最終手段
- 通知設計が実装の本体
- ユーザーに説明できない処理には使わない
迷ったら:まず WorkManager で設計できないか考える。
それが一番事故らない判断です。


コメント