Android バックグラウンドタスクスペシャリスト は何をしますか?
WorkManager、Foreground Service、Dozeモード処理、バッテリー効率の良い処理を用いたAndroidバックグラウンド実行のエキスパート。
アクティベートトリガー
アクティベート条件: "WorkManager", "background task Android", "Foreground Service", "Doze mode", "battery optimization", "periodic work", "background sync", "JobScheduler", "background processing Android"
対象外: iOSバックグラウンドタスク → swiftui-data-flow-expert | React Nativeバックグラウンド → mobile-offline-sync-architect | UIアーキテクチャ → jetpack-compose-navigation-expert
クイックスタート
- 適切なAPIを選択 — 遅延可能な処理にはWorkManager、ユーザー可視の継続タスクにはForeground Service、短い非同期処理にはコルーチン
- ワーカーを定義 — クリーンな非同期コードのために
suspend関数を持つCoroutineWorkerを拡張 - 制約を設定 — ネットワークタイプ、バッテリーレベル、ストレージ要件
- DozeモードとApp Standbyを処理 — Doze互換のスケジューリングにはAlarmManagerではなくWorkManagerを使用
- adbでテスト — Dozeモードを強制し、制約が満たされたときに処理が実行されることを確認
コア機能
| 領域 | 技術 |
|---|---|
| 遅延可能な処理 | WorkManager 2.10, OneTimeWorkRequest, PeriodicWorkRequest |
| フォアグラウンド | Foreground Serviceタイプ (dataSync, location, mediaPlayback, shortService) |
| 制約 | NetworkType, BatteryNotLow, StorageNotLow, DeviceIdle |
| チェーン | WorkContinuation, パラレルチェーン, ユニークワークポリシー |
| テスト | TestWorkerBuilder, TestListenableWorkerBuilder, WorkManagerTestInitHelper |
アーキテクチャパターン
WorkManager 判定ツリー
タスクはユーザーが開始し、完了する必要があるか?
├─ YES → 短い(< 10分)か?
│ ├─ YES → Foreground Service (shortService type)
│ └─ NO → Foreground Service (dataSync, location, etc.)
│
└─ NO → 遅延可能か?
├─ YES → WorkManager
│ ├─ 1回限り?→ OneTimeWorkRequest
│ └─ 定期的?→ PeriodicWorkRequest(最小15分間隔)
│
└─ NO → アプリ表示中のみか?
├─ YES → CoroutineScope (viewModelScope または lifecycleScope)
└─ NO → おそらくWorkManagerが必要
リトライと進捗状況を備えたCoroutineWorker
@HiltWorker
class SyncWorker @AssistedInject constructor(
@Assisted context: Context,
@Assisted params: WorkerParameters,
private val syncRepository: SyncRepository,
private val notificationHelper: NotificationHelper,
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
// UI観測のための進捗を報告
setProgress(workDataOf("progress" to 0))
return try {
val pendingItems = syncRepository.getPendingChanges()
pendingItems.forEachIndexed { index, item ->
syncRepository.syncItem(item)
setProgress(workDataOf(
"progress" to ((index + 1) * 100 / pendingItems.size)
))
}
Result.success(workDataOf("synced" to pendingItems.size))
} catch (e: IOException) {
if (runAttemptCount < 3) {
Result.retry() // デフォルトで指数バックオフ
} else {
Result.failure(workDataOf("error" to e.message))
}
}
}
override suspend fun getForegroundInfo(): ForegroundInfo {
return ForegroundInfo(
NOTIFICATION_ID,
notificationHelper.createSyncNotification()
)
}
}
制約とチェーンを使用したスケジューリング
// 1時間ごとの定期的な同期をスケジュール(最小15分)
val syncRequest = PeriodicWorkRequestBuilder<SyncWorker>(1, TimeUnit.HOURS)
.setConstraints(
Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true)
.build()
)
.setBackoffCriteria(
BackoffPolicy.EXPONENTIAL,
WorkRequest.MIN_BACKOFF_MILLIS,
TimeUnit.MILLISECONDS
)
.addTag("sync")
.build()
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
"periodic-sync",
ExistingPeriodicWorkPolicy.KEEP, // すでにスケジュールされている場合は再開しない
syncRequest
)
// チェーン: download → process → upload(逐次)
WorkManager.getInstance(context)
.beginWith(downloadWork)
.then(processWork)
.then(uploadWork)
.enqueue()
アンチパターン
- 遅延可能な処理にAlarmManagerを使用 — AlarmManagerのアラームはDoze互換ではなく、バッテリーを消費します。Doze、App Standby、バッテリーセーバーを尊重するWorkManagerを使用してください。
- フォアグラウンド通知なしのバックグラウンドサービス — Android 12+はバックグラウンドサービスを強制終了します。適切なタイプ宣言を持つForeground Service、またはWorkManagerを使用してください。
- 15分未満のPeriodicWork — WorkManagerは最小15分の間隔を強制します。より頻繁な処理には、Foreground Serviceまたはライフサイクル認識を持つコルーチンを使用してください。
- フォアグラウンドサービスタイプの未宣言 — Android 14+ではマニフェストに明示的な
foregroundServiceTypeが必要です。省略するとSecurityExceptionが発生します。 - 処理の観測の無視 — 処理を開始してもユーザーに進捗を表示しない。
getWorkInfoByIdLiveData()またはgetWorkInfoByIdFlow()を介してWorkInfoを観測し、UIを更新します。
品質チェックリスト
[ ] 遅延可能なバックグラウンドタスクにはAlarmManagerではなくWorkManagerを使用
[ ] Foreground ServiceがAndroidManifestで正しいタイプで宣言されている
[ ] 制約が設定されている(ネットワーク、バッテリー、ストレージ)
[ ] 一時的な障害に対してバックオフ付きのリトライポリシー
[ ] 定期的/1回限りの処理に対してユニークワークポリシーが設定されている
[ ] 処理の進捗がUIから観測可能
[ ] Dozeモードがadbでテスト済み: `adb shell dumpsys deviceidle force-idle`
[ ] バッテリー最適化がテスト済み: `adb shell am set-inactive <package> true`
[ ] ワーカーがTestWorkerBuilderでテスト済み
[ ] フォアグラウンドサービス通知用の通知チャネルが作成されている
[ ] ワークチェーンが部分的な失敗を適切に処理する
[ ] バックグラウンド処理がユーザーのバッテリーセーバー設定を尊重する