


implementation("androidx.work:work-runtime-ktx:$work_version")

val continuation = WorkManager.getInstance(context)
.beginUniqueWork(
Constants.IMAGE_MANIPULATION_WORK_NAME,
ExistingWorkPolicy.REPLACE,
OneTimeWorkRequest.from(CleanupWorker::class.java)
).then(OneTimeWorkRequest.from(WaterColorFilterWorker::class.java))
.then(OneTimeWorkRequest.from(GrayScaleFilterWorker::class.java))
.then(OneTimeWorkRequest.from(BlurEffectFilterWorker::class.java))
.then(
if (save) {
workRequest<SaveImageToGalleryWorker>(tag = Constants.TAG_OUTPUT)
} else /* upload */ {
workRequest<UploadWorker>(tag = Constants.TAG_OUTPUT)
}
)
이미지를 다운로드를 받으면서 알림으로 다운로드 시작 알리는 기능을 구현해보자.
class ImageDownloader(
private val context: Context,
params: WorkerParameters,
) : CoroutineWorker(context, params) {
private val notificationManager by lazy {
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
}
override suspend fun doWork(): Result {
createNotificationChannel()
return withContext(Dispatchers.IO) {
try {
val imageUrl = ""
imageUrl.let {
notificationManager.notify(NOTIFICATION_ID, createNotification())
val inputStream = BufferedInputStream(URL(imageUrl).openStream())
val bitmap = BitmapFactory.decodeStream(inputStream)
val file = saveBitmapToFile(bitmap)
val outputData = workDataOf(KEY_IMAGE_FILE_PATH to file.toString())
Result.success(outputData)
}
} catch (e: Exception) {
Log.e(TAG, "Error downloading image", e)
Result.failure()
}
}
}
private fun saveBitmapToFile(bitmap: Bitmap): Uri {
val fileName = "image_${System.currentTimeMillis()}.png"
val file = File(applicationContext.filesDir, fileName)
val outputStream = FileOutputStream(file)
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
outputStream.close()
return FileProvider.getUriForFile(
applicationContext,
"${applicationContext.packageName}.fileprovider",
file
)
}
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
NOTIFICATION_CHANNEL_ID,
"WorkManager Start Channel",
NotificationManager.IMPORTANCE_DEFAULT
)
notificationManager.createNotificationChannel(channel)
}
}
private fun createNotification(): Notification {
return NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
.setContentTitle("다운로드")
.setContentText("이미지 다운로드를 시작합니다.")
.setSmallIcon(R.drawable.baseline_notifications_24)
.build()
}
companion object {
private const val TAG = "ImageDownloadWorker"
const val KEY_IMAGE_URL = "image_url"
const val KEY_IMAGE_FILE_PATH = "image_file_path"
const val NOTIFICATION_CHANNEL_ID = "MyForegroundServiceChannel"
const val NOTIFICATION_ID = 12345
}
}
에뮬레이터에서 파일이 저장되었는지 확인하고 싶으면 /data/data/packageName/files 를 찾아가면 볼 수 있다.
Worker 클래스를 상속해서 doWork() 메서드 안에 백그라운드에서 해야 할 작업을 명시하고 Result를 반환
Result.success() - 성공
Result.failure() - 실패
Result.retry() - 실패했고 재시도해야 함
private val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
val imageDownloadRequest = OneTimeWorkRequestBuilder<ImageDownloader>()
.setConstraints(constraints)
.build()
Periodical Work
val myUploadWork = PeriodicWorkRequestBuilder<SaveImageToFileWorker>(
1, TimeUnit.HOURS, // repeatInterval (the period cycle)
15, TimeUnit.MINUTES) // flexInterval
.build()

WorkManager.getInstance(context).enqueue(imageDownloadRequest)
Worker
CoroutineWorker
RxWorker
ListenableWorker
https://developer.android.com/develop/background-work/background-tasks
https://developer.android.com/develop/background-work/background-tasks/persistent/getting-started
https://developer.android.com/develop/background-work/background-tasks/persistent/threading