昨天有介紹 使用 AlarmManager 設定定時任務,AlarmManager 是負責處理精確時間的任務。
而本篇要介紹的 WorkManager 則是依照特定條件,例如已連上 wifi,正在充電中、手機閒置時等狀態來觸發任務。例如要將使用者的個人設定值上傳到伺服器中,但是剛好現在又沒有連線到網路,就可以使用 WorkManager 來註冊任務,當有 wifi 時再上傳,對於不需要即時處理的任務來說非常好用,並且在任務中還可以回傳需要重試的狀態,讓系統自動安排再次執行。
不過在使用前需要注意的是 WorkManager 並沒有辦法精確指定時間,例如下面將要建立的範例是使用 WorkManager 註冊一個任務,當連上 wifi 時呼叫 API 。
在有連上 wifi 時 大多數時候 都會立刻執行(也有少部分是會需要等好幾分鐘),而在比較特別的案例例如先關閉 wifi ,開啟 App 註冊任務後關閉 App ,再開啟 wifi ,在筆者的測試中大約需要經過 30 秒到 15 分鐘不等的時間才會呼叫 API,所以只適合不緊急的任務。
另外也因為在筆者測試時發現就算不關閉 App,有時候也不會立刻執行,是等待幾分鐘後才執行,所以也不要都只使用 WorkManager ,以「上傳使用者設定值」這個案例來說,建議先檢查網路情況,有網路連線就直接上傳,否則再使用 WorkManager ,避免無法即時處理。
這裡的範例是建立呼叫 API 的任務:
建立任務:
參考資料:
Android Developers - Schedule tasks with WorkManager
Android Developers - WorkManager
不過在使用前需要注意的是 WorkManager 並沒有辦法精確指定時間,例如下面將要建立的範例是使用 WorkManager 註冊一個任務,當連上 wifi 時呼叫 API 。
在有連上 wifi 時 大多數時候 都會立刻執行(也有少部分是會需要等好幾分鐘),而在比較特別的案例例如先關閉 wifi ,開啟 App 註冊任務後關閉 App ,再開啟 wifi ,在筆者的測試中大約需要經過 30 秒到 15 分鐘不等的時間才會呼叫 API,所以只適合不緊急的任務。
另外也因為在筆者測試時發現就算不關閉 App,有時候也不會立刻執行,是等待幾分鐘後才執行,所以也不要都只使用 WorkManager ,以「上傳使用者設定值」這個案例來說,建議先檢查網路情況,有網路連線就直接上傳,否則再使用 WorkManager ,避免無法即時處理。
程式碼
建立 MyApiWorker.kt,把任務執行時要做的事情放在這裡,這是最簡單的示範:
import android.content.Context
import android.util.Log
import androidx.work.Worker
import androidx.work.WorkerParameters
class MyApiWorker(context: Context, workerParams: WorkerParameters) :
Worker(context, workerParams) {
override fun doWork(): Result {
Log.i("MyApiWorker", "執行任務")
return Result.success() // 成功
// return Result.failure() // 失敗
// return Result.retry() // 失敗,要求重試
}
}
這裡的範例是建立呼叫 API 的任務:
import android.content.Context
import android.util.Log
import androidx.work.Worker
import androidx.work.WorkerParameters
import java.io.BufferedReader
import java.io.InputStreamReader
import java.net.HttpURLConnection
import java.net.URL
class MyApiWorker(context: Context, workerParams: WorkerParameters) :
Worker(context, workerParams) {
override fun doWork(): Result {
val url = URL("https://cdn.jsdelivr.net/gh/ruyut/TaiwanCalendar/data/2024.json")
val urlConnection: HttpURLConnection
return try {
urlConnection = url.openConnection() as HttpURLConnection
urlConnection.requestMethod = "GET"
val responseCode = urlConnection.responseCode
if (responseCode == HttpURLConnection.HTTP_OK) {
val bufferedReader = BufferedReader(InputStreamReader(urlConnection.inputStream))
val response = StringBuilder()
bufferedReader.useLines { lines -> lines.forEach { response.append(it) } }
Log.d("MyApiWorker","API Response: $response")
Result.success()
} else {
Log.e("MyApiWorker", "API Response Code: $responseCode")
Result.failure()
}
} catch (e: Exception) {
Log.e("MyApiWorker", "API Call failed", e)
Result.failure()
}
}
}
建立任務:
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED) // 只在連上 WiFi 時觸發
.build()
val apiCallWorkRequest = OneTimeWorkRequestBuilder<MyApiWorker>()
.setConstraints(constraints)
.build()
val context: Context = LocalContext.current
WorkManager.getInstance(context).enqueue(apiCallWorkRequest)
參考資料:
Android Developers - Schedule tasks with WorkManager
Android Developers - WorkManager
留言
張貼留言
如果有任何問題、建議、想說的話或文章題目推薦,都歡迎留言或來信: a@ruyut.com