AndroidでWorkManagerを使って定期的にバックグラウンド処理を行う方法
Androidアプリで「定期的にサーバーへデータ送信したい」「1日1回キャッシュをクリアしたい」といった処理、よくありますよね。
今回は、WorkManagerを使って安定したバックグラウンド処理を実装する方法を紹介します。
WorkManagerとは?
WorkManagerは、Android Jetpackの一部で、アプリが終了していても、一定の条件下でバックグラウンド処理を実行できる仕組みです。
以前はAlarmManagerやJobSchedulerを使うことが多かったですが、WorkManagerを使えばOSバージョンごとの差異を気にせずに実装できます。
依存関係の追加
// build.gradle(:app)
dependencies {
implementation("androidx.work:work-runtime-ktx:2.9.1")
}
基本的な使い方
まずは、シンプルなWorkerクラスを作成します。
ここではログを出力するだけのサンプルです。
class LogWorker(
context: Context,
workerParams: WorkerParameters
) : Worker(context, workerParams) {
override fun doWork(): Result {
Log.d("LogWorker", "バックグラウンド処理が実行されました!")
return Result.success()
}
}
doWork()
の中に実際の処理を書きます。
このメソッドはワーカースレッド上で実行されるため、UI更新などは行わないように注意しましょう。
一度だけ実行する
val workRequest = OneTimeWorkRequestBuilder<LogWorker>().build()
WorkManager.getInstance(context).enqueue(workRequest)
これで、一度だけバックグラウンド処理を実行できます。
アプリを閉じても再起動後に自動で処理が実行される点が便利です。
定期的に実行する(PeriodicWorkRequest)
val periodicWorkRequest =
PeriodicWorkRequestBuilder<LogWorker>(15, TimeUnit.MINUTES)
.build()
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
"PeriodicLog",
ExistingPeriodicWorkPolicy.KEEP,
periodicWorkRequest
)
上記の例では、15分ごとにバックグラウンドで処理を実行します。enqueueUniquePeriodicWork
を使うと、重複登録を防げるのがポイントです。
ネットワーク接続中のみ実行したい場合
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
val workRequest = OneTimeWorkRequestBuilder<LogWorker>()
.setConstraints(constraints)
.build()
WorkManager.getInstance(context).enqueue(workRequest)
Constraint(制約)を使うことで、
「Wi-Fi接続中のみ」「充電中のみ」など、状況に応じた制御も可能です。
バックオフポリシーの設定
通信エラーやタイムアウト時に再試行したい場合は、バックオフ設定を行います。
val workRequest = OneTimeWorkRequestBuilder<LogWorker>()
.setBackoffCriteria(
BackoffPolicy.LINEAR,
10,
TimeUnit.SECONDS
)
.build()
これにより、失敗時は10秒後に再試行されます。
指数的に増やす BackoffPolicy.EXPONENTIAL
に切り替えることもできます。
実践例:サーバー同期処理
class SyncWorker(
context: Context,
params: WorkerParameters
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
return try {
val response = HttpURLConnection(URL("https://api.example.com/sync")).apply {
requestMethod = "GET"
connectTimeout = 5000
readTimeout = 5000
}.inputStream.bufferedReader().readText()
Log.d("SyncWorker", "同期成功: $response")
Result.success()
} catch (e: Exception) {
Log.e("SyncWorker", "同期失敗", e)
Result.retry()
}
}
}
実際の通信処理はRetrofitを使ってもOKですが、標準のHttpURLConnectionでも十分実用的です。
例外発生時に Result.retry()
を返せば、自動的に再試行されます。
まとめ
- WorkManagerはバックグラウンド処理を安全に実行できる
- PeriodicWorkRequestで定期実行も可能
- ConstraintやBackoffを使えばより信頼性の高い実装ができる
Firebaseの同期やキャッシュ削除、アナリティクス送信など、
「ユーザー操作に依存しない処理」を安定的に動かしたいときにWorkManagerは本当に便利です。
一度仕組みを理解しておくと、アプリの品質がぐっと上がりますよ。
コメント