깨알 개념/Android

[Android] WorkManager - 기초

interfacer_han 2024. 6. 17. 20:02

#1 이전 글

 

[Android] WorkManager - 개요

#1 WorkManager는 '지연 가능한 백그라운드 작업'의 관리자 WorkManager를 사용한 백그라운드 작업 - Kotlin | Android DevelopersAndroid에는 보장된 백그라운드 작업을 위한 다수의 옵션이 있으며, 이러한 옵션

kenel.tistory.com

개념 설명에 그쳤던 이전 글에 이어 본 게시글에선 실제로 WorkManager를 구현해본다.

 

#2 WorkManager 사용하기

#2-1 모듈 수준 build.gradle 수정

plugins {
    ...
}

android {
    ...
}

dependencies {

    ...

    // WorkManager
    val work_version = "2.9.0"
    implementation("androidx.work:work-runtime-ktx:$work_version") // Kotlin + coroutines
}

여기에 있는 코드를 복사하여 모듈 수준 build.gradle의 dependencies { ... }에 추가한다.

 

#2-2 Worker 클래스 만들기 - UploadWorker.kt

// package com.example.workmanagerbasics

import android.content.Context
import android.util.Log
import androidx.work.Worker
import androidx.work.WorkerParameters
import java.text.SimpleDateFormat
import java.util.Date

class UploadWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
    override fun doWork(): Result {
        try {
            Log.i("interfacer_han", "(${this::class.simpleName}) Started at ${getNowTime()}")

            for (i in 0..100) {
                Log.i("interfacer_han", "(${this::class.simpleName}) Progress: ${i}/100")
            }

            Log.i("interfacer_han", "(${this::class.simpleName}) Finished at ${getNowTime()}")
            return Result.success()

        } catch (e: Exception) {
            return Result.failure()
        }
    }

    private fun getNowTime(): String {
        val time = SimpleDateFormat("yyyy/MM/dd hh:mm:ss")
        return time.format(Date())
    }
}

Worker() 클래스를 상속받고, 필수적으로 오버라이드해야 하는 함수인 doWork()를 오버라이드한다. 이 함수 안에는 실질적으로 의미를 갖는 작업들 가령 서버에 파일을 Upload하는 작업이 아니라, 더미 작업들을 넣었다. 또, try { ... } catch { ... } 문으로 분기를 나눠 작업이 실패한 경우도 return할 수 있게 한다.

 

#2-3 Worker 클래스 만들기 - DownloadWorker.kt

#2-2와 내용이 완전히 동일하지만, 파일 명 및 클래스 이름만 다르게 만든다.

 

#2-4 activity_main.xml 수정

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/oneTimeButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="One Time Request"
        android:textSize="40dp"
        app:layout_constraintBottom_toTopOf="@+id/periodicButton"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/periodicButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Periodic Request"
        android:textSize="40dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/oneTimeButton" />
</androidx.constraintlayout.widget.ConstraintLayout>

버튼이 2개 있는 간단한 View를 만든다. 이전 게시글의 #4-3처럼, 첫번째 버튼은 1회성 수행 (One Time)을 위한 버튼이고 2번째 버튼은 주기적 수행 (Periodic)을 위한 버튼이다.

 

#2-5 MainActivity.kt - onCreate()

// package com.example.workmanagerbasics

import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import androidx.work.WorkManager

lateinit var workManager: WorkManager

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        workManager = WorkManager.getInstance(applicationContext)

        val oneTimeButton = findViewById<Button>(R.id.oneTimeButton)
        val periodicButton = findViewById<Button>(R.id.periodicButton)

        oneTimeButton.setOnClickListener {
            setOneTimeWorkRequest()
        }

        periodicButton.setOnClickListener {
            setPeriodicWorkRequest()
        }
    }

    private fun setOneTimeWorkRequest() {
        TODO()
    }

    private fun setPeriodicWorkRequest() {
        TODO()
}

MainActivity에서 사용할 WorkManager 객체의 프로퍼티를 선언하고 onCreate()를 작성한다. #2-4에서 만들었던 첫번째 버튼을 클릭하면 setOneTimeWorkRequest(), 2번째 버튼을 클릭하면 setPeriodicWorkRequest()가 실행되게 만든다.

 

#2-6 MainActivity.kt - setOneTimeWorkRequest()

// package com.example.workmanagerbasics

...
import android.util.Log
import androidx.lifecycle.Observer
import androidx.work.OneTimeWorkRequest

lateinit var workManager: WorkManager

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
    }

    private fun setOneTimeWorkRequest() {
        // WorkRequest 객체 만들기
        val uploadRequest = OneTimeWorkRequest
            .Builder(UploadWorker::class.java)
            .build()

        // WorkManager 객체의 작업 큐(Job queue)에 WorkRequest 등록
        workManager.enqueue(uploadRequest)

        // WorkInfo는 작업에 대한 정보를 담은 객체.
        // WorkManager.getWorkInfoByIdLiveData()는 LiveData<WorkInfo>를 반환.
        val workInfo = workManager.getWorkInfoByIdLiveData(uploadRequest.id)
        workInfo.observe(this, Observer {
            Log.i("interfacer_han", "(${this::class.simpleName}) UploadWorker's state: ${it.state.name}")
        })
    }

    private fun setPeriodicWorkRequest() {
        TODO()
    }
}

빌더 클래스로 WorkRequest 객체를 만들고, 이를 WorkerManager에 넣는다.

WorkManager.enqueue(request: WorkRequest)WorkRequest를 WorkManager의 작업 큐에 등록한다. WorkInfo는 진행 중인 작업에 대한 정보를 LiveData의 형태로 제공한다

따라서, WorkInfo를 LiveData.observe()하는 것으로 작업의 진행 상태(state)를 실시간으로 확인할 수 있다 (본 게시글의 #3 참조).

 

#2-7 MainActivity.kt - setPeriodicWorkRequest()

// package com.example.workmanagerbasics

...
import androidx.work.PeriodicWorkRequest
import java.util.concurrent.TimeUnit

lateinit var workManager: WorkManager

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
    }

    private fun setOneTimeWorkRequest() {
        ...
    }

    private fun setPeriodicWorkRequest() {
        // WorkRequest 객체 만들기
        val downloadRequest = PeriodicWorkRequest
            .Builder(DownloadWorker::class.java, 15, TimeUnit.MINUTES) // 안드로이드에서 허용하는 PeriodicWorkRequest의 최소 주기는 15분이다.
            .build()

        // WorkManager 객체의 작업 큐(Job queue)에 WorkRequest 등록
        workManager.enqueue(downloadRequest)

        // WorkInfo는 작업에 대한 정보를 담은 객체.
        // WorkManager.getWorkInfoByIdLiveData()는 LiveData<WorkInfo>를 반환.
        val workInfo = workManager.getWorkInfoByIdLiveData(downloadRequest.id)
        workInfo.observe(this, Observer {
            Log.i("interfacer_han", "(${this::class.simpleName}) DownloadWorker's state: ${it.state.name}")
        })
    }
}

#2-6와 전체적으로 비슷하다. 세부적으로는 WorkManager 라이브러리에서 끌어다 쓰는 함수들의 이름이 조금씩 다르다는 차이가 있다. 그 중에서, WorkRequest의 빌더 클래스가 요구하는 인자가 1개가 아니라 3개라는 점이 주요한 차이다. PeriodicWorkRequest는 이름처럼 주기(period)를 가지는데, 이 주기마다 안드로이드 시스템에서 해당 Worker가 실행된다 (여기에서는 DownloadWorker). 안드로이드에서 허용하는 최소 주기는 15분이다.

 

#3 작업의 상태(State)

 

WorkInfo.State  |  Android Developers

androidx.compose.desktop.ui.tooling.preview

developer.android.com

WorkInfo.state에는 BLOCKED, ENQUEUED, RUNNING, SUCCEEDED, FAIL, CACELLED의 6가지 상태가 있다.

BLOCKED는 B작업에 대한 WorkInfo을 살펴보려고 할 때, B 작업의 선행 작업 A가 완료되지 않아서 순서 상 A에게 종속된(= 뒤에 있는) B의 실행이 유예된(≠ 실패한) 상태다. (선행 작업 및 후행 작업에 대한 개념은 이 게시글 참조)

ENQUEUED는 지정된 조건(인터넷 연결이나 충분한 RAM 등)을 기다리느라 작업이 아직 시작되지 않고 실행 대기열에만 존재하는 상태다.

RUNNING은 말 그대로 작업이 진행중인 상태다.

SUCCEEDED는 작업이 성공한 상태다
FAILED는 작업이 실패한 상태다. BLOCKED과 같은 맥락으로, 순서 상으로 종속된 후행 작업들도 전부 FAILED로 변경된다. BLOCKED와는 반대로 후행 작업들이 실패 처리된(≠ 유예된) 상태라는 것에 유의하자. (선행 작업 및 후행 작업에 대한 개념은 이 게시글 참조)

CANCELLED는 프로그래머가 명시적으로 작업을 취소했거나 시스템에 의해 취소된 경우다.

 

PeriodicWorkRequest는 BLOCKED, SUCCEEDED, FAILED 상태를 가질 수 없다. #4-3을 참고하자.

 

#4 작동 확인

#4-1 View의 모습

 

#4-2 'One Time Request' 버튼을 클릭했을 때의 로그 메시지

더보기
(MainActivity) UploadWorker's state: ENQUEUED
(MainActivity) UploadWorker's state: RUNNING
(UploadWorker) Started at 2024/06/17 12:42:04
(UploadWorker) Progress: 0/100
(UploadWorker) Progress: 1/100
(UploadWorker) Progress: 2/100
(UploadWorker) Progress: 3/100
(UploadWorker) Progress: 4/100
(UploadWorker) Progress: 5/100
(UploadWorker) Progress: 6/100
(UploadWorker) Progress: 7/100
(UploadWorker) Progress: 8/100
(UploadWorker) Progress: 9/100
(UploadWorker) Progress: 10/100
(UploadWorker) Progress: 11/100
(UploadWorker) Progress: 12/100
(UploadWorker) Progress: 13/100
(UploadWorker) Progress: 14/100
(UploadWorker) Progress: 15/100
(UploadWorker) Progress: 16/100
(UploadWorker) Progress: 17/100
(UploadWorker) Progress: 18/100
(UploadWorker) Progress: 19/100
(UploadWorker) Progress: 20/100
(UploadWorker) Progress: 21/100
(UploadWorker) Progress: 22/100
(UploadWorker) Progress: 23/100
(UploadWorker) Progress: 24/100
(UploadWorker) Progress: 25/100
(UploadWorker) Progress: 26/100
(UploadWorker) Progress: 27/100
(UploadWorker) Progress: 28/100
(UploadWorker) Progress: 29/100
(UploadWorker) Progress: 30/100
(UploadWorker) Progress: 31/100
(UploadWorker) Progress: 32/100
(UploadWorker) Progress: 33/100
(UploadWorker) Progress: 34/100
(UploadWorker) Progress: 35/100
(UploadWorker) Progress: 36/100
(UploadWorker) Progress: 37/100
(UploadWorker) Progress: 38/100
(UploadWorker) Progress: 39/100
(UploadWorker) Progress: 40/100
(UploadWorker) Progress: 41/100
(UploadWorker) Progress: 42/100
(UploadWorker) Progress: 43/100
(UploadWorker) Progress: 44/100
(UploadWorker) Progress: 45/100
(UploadWorker) Progress: 46/100
(UploadWorker) Progress: 47/100
(UploadWorker) Progress: 48/100
(UploadWorker) Progress: 49/100
(UploadWorker) Progress: 50/100
(UploadWorker) Progress: 51/100
(UploadWorker) Progress: 52/100
(UploadWorker) Progress: 53/100
(UploadWorker) Progress: 54/100
(UploadWorker) Progress: 55/100
(UploadWorker) Progress: 56/100
(UploadWorker) Progress: 57/100
(UploadWorker) Progress: 58/100
(UploadWorker) Progress: 59/100
(UploadWorker) Progress: 60/100
(UploadWorker) Progress: 61/100
(UploadWorker) Progress: 62/100
(UploadWorker) Progress: 63/100
(UploadWorker) Progress: 64/100
(UploadWorker) Progress: 65/100
(UploadWorker) Progress: 66/100
(UploadWorker) Progress: 67/100
(UploadWorker) Progress: 68/100
(UploadWorker) Progress: 69/100
(UploadWorker) Progress: 70/100
(UploadWorker) Progress: 71/100
(UploadWorker) Progress: 72/100
(UploadWorker) Progress: 73/100
(UploadWorker) Progress: 74/100
(UploadWorker) Progress: 75/100
(UploadWorker) Progress: 76/100
(UploadWorker) Progress: 77/100
(UploadWorker) Progress: 78/100
(UploadWorker) Progress: 79/100
(UploadWorker) Progress: 80/100
(UploadWorker) Progress: 81/100
(UploadWorker) Progress: 82/100
(UploadWorker) Progress: 83/100
(UploadWorker) Progress: 84/100
(UploadWorker) Progress: 85/100
(UploadWorker) Progress: 86/100
(UploadWorker) Progress: 87/100
(UploadWorker) Progress: 88/100
(UploadWorker) Progress: 89/100
(UploadWorker) Progress: 90/100
(UploadWorker) Progress: 91/100
(UploadWorker) Progress: 92/100
(UploadWorker) Progress: 93/100
(UploadWorker) Progress: 94/100
(UploadWorker) Progress: 95/100
(UploadWorker) Progress: 96/100
(UploadWorker) Progress: 97/100
(UploadWorker) Progress: 98/100
(UploadWorker) Progress: 99/100
(UploadWorker) Progress: 100/100
(UploadWorker) Finished at 2024/06/17 12:42:04
(MainActivity) UploadWorker's state: SUCCEEDED

 

#4-3 'Periodic Request' 버튼을 클릭했을 때의 로그 메시지

더보기
(MainActivity) DownloadWorker's state: ENQUEUED
(MainActivity) DownloadWorker's state: RUNNING
(DownloadWorker) Started at 2024/06/17 12:52:41
(DownloadWorker) Progress: 0/100
(DownloadWorker) Progress: 1/100
(DownloadWorker) Progress: 2/100
(DownloadWorker) Progress: 3/100
(DownloadWorker) Progress: 4/100
(DownloadWorker) Progress: 5/100
(DownloadWorker) Progress: 6/100
(DownloadWorker) Progress: 7/100
(DownloadWorker) Progress: 8/100
(DownloadWorker) Progress: 9/100
(DownloadWorker) Progress: 10/100
(DownloadWorker) Progress: 11/100
(DownloadWorker) Progress: 12/100
(DownloadWorker) Progress: 13/100
(DownloadWorker) Progress: 14/100
(DownloadWorker) Progress: 15/100
(DownloadWorker) Progress: 16/100
(DownloadWorker) Progress: 17/100
(DownloadWorker) Progress: 18/100
(DownloadWorker) Progress: 19/100
(DownloadWorker) Progress: 20/100
(DownloadWorker) Progress: 21/100
(DownloadWorker) Progress: 22/100
(DownloadWorker) Progress: 23/100
(DownloadWorker) Progress: 24/100
(DownloadWorker) Progress: 25/100
(DownloadWorker) Progress: 26/100
(DownloadWorker) Progress: 27/100
(DownloadWorker) Progress: 28/100
(DownloadWorker) Progress: 29/100
(DownloadWorker) Progress: 30/100
(DownloadWorker) Progress: 31/100
(DownloadWorker) Progress: 32/100
(DownloadWorker) Progress: 33/100
(DownloadWorker) Progress: 34/100
(DownloadWorker) Progress: 35/100
(DownloadWorker) Progress: 36/100
(DownloadWorker) Progress: 37/100
(DownloadWorker) Progress: 38/100
(DownloadWorker) Progress: 39/100
(DownloadWorker) Progress: 40/100
(DownloadWorker) Progress: 41/100
(DownloadWorker) Progress: 42/100
(DownloadWorker) Progress: 43/100
(DownloadWorker) Progress: 44/100
(DownloadWorker) Progress: 45/100
(DownloadWorker) Progress: 46/100
(DownloadWorker) Progress: 47/100
(DownloadWorker) Progress: 48/100
(DownloadWorker) Progress: 49/100
(DownloadWorker) Progress: 50/100
(DownloadWorker) Progress: 51/100
(DownloadWorker) Progress: 52/100
(DownloadWorker) Progress: 53/100
(DownloadWorker) Progress: 54/100
(DownloadWorker) Progress: 55/100
(DownloadWorker) Progress: 56/100
(DownloadWorker) Progress: 57/100
(DownloadWorker) Progress: 58/100
(DownloadWorker) Progress: 59/100
(DownloadWorker) Progress: 60/100
(DownloadWorker) Progress: 61/100
(DownloadWorker) Progress: 62/100
(DownloadWorker) Progress: 63/100
(DownloadWorker) Progress: 64/100
(DownloadWorker) Progress: 65/100
(DownloadWorker) Progress: 66/100
(DownloadWorker) Progress: 67/100
(DownloadWorker) Progress: 68/100
(DownloadWorker) Progress: 69/100
(DownloadWorker) Progress: 70/100
(DownloadWorker) Progress: 71/100
(DownloadWorker) Progress: 72/100
(DownloadWorker) Progress: 73/100
(DownloadWorker) Progress: 74/100
(DownloadWorker) Progress: 75/100
(DownloadWorker) Progress: 76/100
(DownloadWorker) Progress: 77/100
(DownloadWorker) Progress: 78/100
(DownloadWorker) Progress: 79/100
(DownloadWorker) Progress: 80/100
(DownloadWorker) Progress: 81/100
(DownloadWorker) Progress: 82/100
(DownloadWorker) Progress: 83/100
(DownloadWorker) Progress: 84/100
(DownloadWorker) Progress: 85/100
(DownloadWorker) Progress: 86/100
(DownloadWorker) Progress: 87/100
(DownloadWorker) Progress: 88/100
(DownloadWorker) Progress: 89/100
(DownloadWorker) Progress: 90/100
(DownloadWorker) Progress: 91/100
(DownloadWorker) Progress: 92/100
(DownloadWorker) Progress: 93/100
(DownloadWorker) Progress: 94/100
(DownloadWorker) Progress: 95/100
(DownloadWorker) Progress: 96/100
(DownloadWorker) Progress: 97/100
(DownloadWorker) Progress: 98/100
(DownloadWorker) Progress: 99/100
(DownloadWorker) Progress: 100/100
(DownloadWorker) Finished at 2024/06/17 12:52:41
(MainActivity) DownloadWorker's state: ENQUEUED
(DownloadWorker) Started at 2024/06/17 01:07:41
(DownloadWorker) Progress: 0/100
(DownloadWorker) Progress: 1/100
(DownloadWorker) Progress: 2/100
(DownloadWorker) Progress: 3/100
(DownloadWorker) Progress: 4/100
(DownloadWorker) Progress: 5/100
(DownloadWorker) Progress: 6/100
(DownloadWorker) Progress: 7/100
(DownloadWorker) Progress: 8/100
(DownloadWorker) Progress: 9/100
(DownloadWorker) Progress: 10/100
(DownloadWorker) Progress: 11/100
(DownloadWorker) Progress: 12/100
(DownloadWorker) Progress: 13/100
(DownloadWorker) Progress: 14/100
(DownloadWorker) Progress: 15/100
(DownloadWorker) Progress: 16/100
(DownloadWorker) Progress: 17/100
(DownloadWorker) Progress: 18/100
(DownloadWorker) Progress: 19/100
(DownloadWorker) Progress: 20/100
(MainActivity) DownloadWorker's state: RUNNING
(DownloadWorker) Progress: 21/100
(DownloadWorker) Progress: 22/100
(DownloadWorker) Progress: 23/100
(DownloadWorker) Progress: 24/100
(DownloadWorker) Progress: 25/100
(DownloadWorker) Progress: 26/100
(DownloadWorker) Progress: 27/100
(DownloadWorker) Progress: 28/100
(DownloadWorker) Progress: 29/100
(DownloadWorker) Progress: 30/100
(DownloadWorker) Progress: 31/100
(DownloadWorker) Progress: 32/100
(DownloadWorker) Progress: 33/100
(DownloadWorker) Progress: 34/100
(DownloadWorker) Progress: 35/100
(DownloadWorker) Progress: 36/100
(DownloadWorker) Progress: 37/100
(DownloadWorker) Progress: 38/100
(DownloadWorker) Progress: 39/100
(DownloadWorker) Progress: 40/100
(DownloadWorker) Progress: 41/100
(DownloadWorker) Progress: 42/100
(DownloadWorker) Progress: 43/100
(DownloadWorker) Progress: 44/100
(DownloadWorker) Progress: 45/100
(DownloadWorker) Progress: 46/100
(DownloadWorker) Progress: 47/100
(DownloadWorker) Progress: 48/100
(DownloadWorker) Progress: 49/100
(DownloadWorker) Progress: 50/100
(DownloadWorker) Progress: 51/100
(DownloadWorker) Progress: 52/100
(DownloadWorker) Progress: 53/100
(DownloadWorker) Progress: 54/100
(DownloadWorker) Progress: 55/100
(DownloadWorker) Progress: 56/100
(DownloadWorker) Progress: 57/100
(DownloadWorker) Progress: 58/100
(DownloadWorker) Progress: 59/100
(DownloadWorker) Progress: 60/100
(DownloadWorker) Progress: 61/100
(DownloadWorker) Progress: 62/100
(DownloadWorker) Progress: 63/100
(DownloadWorker) Progress: 64/100
(DownloadWorker) Progress: 65/100
(DownloadWorker) Progress: 66/100
(DownloadWorker) Progress: 67/100
(DownloadWorker) Progress: 68/100
(DownloadWorker) Progress: 69/100
(DownloadWorker) Progress: 70/100
(DownloadWorker) Progress: 71/100
(DownloadWorker) Progress: 72/100
(DownloadWorker) Progress: 73/100
(DownloadWorker) Progress: 74/100
(DownloadWorker) Progress: 75/100
(DownloadWorker) Progress: 76/100
(DownloadWorker) Progress: 77/100
(DownloadWorker) Progress: 78/100
(DownloadWorker) Progress: 79/100
(DownloadWorker) Progress: 80/100
(DownloadWorker) Progress: 81/100
(DownloadWorker) Progress: 82/100
(DownloadWorker) Progress: 83/100
(DownloadWorker) Progress: 84/100
(DownloadWorker) Progress: 85/100
(DownloadWorker) Progress: 86/100
(DownloadWorker) Progress: 87/100
(DownloadWorker) Progress: 88/100
(DownloadWorker) Progress: 89/100
(DownloadWorker) Progress: 90/100
(DownloadWorker) Progress: 91/100
(DownloadWorker) Progress: 92/100
(DownloadWorker) Progress: 93/100
(DownloadWorker) Progress: 94/100
(DownloadWorker) Progress: 95/100
(DownloadWorker) Progress: 96/100
(DownloadWorker) Progress: 97/100
(DownloadWorker) Progress: 98/100
(DownloadWorker) Progress: 99/100
(DownloadWorker) Progress: 100/100
(DownloadWorker) Finished at 2024/06/17 01:07:41
(MainActivity) DownloadWorker's state: ENQUEUED
(DownloadWorker) Started at 2024/06/17 01:22:41
(DownloadWorker) Progress: 0/100
(DownloadWorker) Progress: 1/100
(DownloadWorker) Progress: 2/100
(DownloadWorker) Progress: 3/100
(DownloadWorker) Progress: 4/100
(DownloadWorker) Progress: 5/100
(DownloadWorker) Progress: 6/100
(DownloadWorker) Progress: 7/100
(DownloadWorker) Progress: 8/100
(DownloadWorker) Progress: 9/100
(DownloadWorker) Progress: 10/100
(DownloadWorker) Progress: 11/100
(DownloadWorker) Progress: 12/100
(DownloadWorker) Progress: 13/100
(DownloadWorker) Progress: 14/100
(DownloadWorker) Progress: 15/100
(DownloadWorker) Progress: 16/100
(DownloadWorker) Progress: 17/100
(DownloadWorker) Progress: 18/100
(DownloadWorker) Progress: 19/100
(DownloadWorker) Progress: 20/100
(DownloadWorker) Progress: 21/100
(DownloadWorker) Progress: 22/100
(DownloadWorker) Progress: 23/100
(DownloadWorker) Progress: 24/100
(DownloadWorker) Progress: 25/100
(DownloadWorker) Progress: 26/100
(DownloadWorker) Progress: 27/100
(DownloadWorker) Progress: 28/100
(DownloadWorker) Progress: 29/100
(DownloadWorker) Progress: 30/100
(DownloadWorker) Progress: 31/100
(DownloadWorker) Progress: 32/100
(DownloadWorker) Progress: 33/100
(DownloadWorker) Progress: 34/100
(DownloadWorker) Progress: 35/100
(DownloadWorker) Progress: 36/100
(DownloadWorker) Progress: 37/100
(DownloadWorker) Progress: 38/100
(DownloadWorker) Progress: 39/100
(DownloadWorker) Progress: 40/100
(MainActivity) DownloadWorker's state: RUNNING
(DownloadWorker) Progress: 41/100
(DownloadWorker) Progress: 42/100
(DownloadWorker) Progress: 43/100
(DownloadWorker) Progress: 44/100
(DownloadWorker) Progress: 45/100
(DownloadWorker) Progress: 46/100
(DownloadWorker) Progress: 47/100
(DownloadWorker) Progress: 48/100
(DownloadWorker) Progress: 49/100
(DownloadWorker) Progress: 50/100
(DownloadWorker) Progress: 51/100
(DownloadWorker) Progress: 52/100
(DownloadWorker) Progress: 53/100
(DownloadWorker) Progress: 54/100
(DownloadWorker) Progress: 55/100
(DownloadWorker) Progress: 56/100
(DownloadWorker) Progress: 57/100
(DownloadWorker) Progress: 58/100
(DownloadWorker) Progress: 59/100
(DownloadWorker) Progress: 60/100
(DownloadWorker) Progress: 61/100
(DownloadWorker) Progress: 62/100
(DownloadWorker) Progress: 63/100
(DownloadWorker) Progress: 64/100
(DownloadWorker) Progress: 65/100
(DownloadWorker) Progress: 66/100
(DownloadWorker) Progress: 67/100
(DownloadWorker) Progress: 68/100
(DownloadWorker) Progress: 69/100
(DownloadWorker) Progress: 70/100
(DownloadWorker) Progress: 71/100
(DownloadWorker) Progress: 72/100
(DownloadWorker) Progress: 73/100
(DownloadWorker) Progress: 74/100
(DownloadWorker) Progress: 75/100
(DownloadWorker) Progress: 76/100
(DownloadWorker) Progress: 77/100
(DownloadWorker) Progress: 78/100
(DownloadWorker) Progress: 79/100
(DownloadWorker) Progress: 80/100
(DownloadWorker) Progress: 81/100
(DownloadWorker) Progress: 82/100
(DownloadWorker) Progress: 83/100
(DownloadWorker) Progress: 84/100
(DownloadWorker) Progress: 85/100
(DownloadWorker) Progress: 86/100
(DownloadWorker) Progress: 87/100
(DownloadWorker) Progress: 88/100
(DownloadWorker) Progress: 89/100
(DownloadWorker) Progress: 90/100
(DownloadWorker) Progress: 91/100
(DownloadWorker) Progress: 92/100
(DownloadWorker) Progress: 93/100
(DownloadWorker) Progress: 94/100
(DownloadWorker) Progress: 95/100
(DownloadWorker) Progress: 96/100
(DownloadWorker) Progress: 97/100
(DownloadWorker) Progress: 98/100
(DownloadWorker) Progress: 99/100
(DownloadWorker) Progress: 100/100
(DownloadWorker) Finished at 2024/06/17 01:22:41
(MainActivity) DownloadWorker's state: ENQUEUED
(DownloadWorker) Started at 2024/06/17 01:37:41
(DownloadWorker) Progress: 0/100
(DownloadWorker) Progress: 1/100
(DownloadWorker) Progress: 2/100
(DownloadWorker) Progress: 3/100
(DownloadWorker) Progress: 4/100
(DownloadWorker) Progress: 5/100
(DownloadWorker) Progress: 6/100
(DownloadWorker) Progress: 7/100
(DownloadWorker) Progress: 8/100
(DownloadWorker) Progress: 9/100
(DownloadWorker) Progress: 10/100
(DownloadWorker) Progress: 11/100
(DownloadWorker) Progress: 12/100
(DownloadWorker) Progress: 13/100
(DownloadWorker) Progress: 14/100
(DownloadWorker) Progress: 15/100
(DownloadWorker) Progress: 16/100
(DownloadWorker) Progress: 17/100
(DownloadWorker) Progress: 18/100
(MainActivity) DownloadWorker's state: RUNNING
(DownloadWorker) Progress: 19/100
(DownloadWorker) Progress: 20/100
(DownloadWorker) Progress: 21/100
(DownloadWorker) Progress: 22/100
(DownloadWorker) Progress: 23/100
(DownloadWorker) Progress: 24/100
(DownloadWorker) Progress: 25/100
(DownloadWorker) Progress: 26/100
(DownloadWorker) Progress: 27/100
(DownloadWorker) Progress: 28/100
(DownloadWorker) Progress: 29/100
(DownloadWorker) Progress: 30/100
(DownloadWorker) Progress: 31/100
(DownloadWorker) Progress: 32/100
(DownloadWorker) Progress: 33/100
(DownloadWorker) Progress: 34/100
(DownloadWorker) Progress: 35/100
(DownloadWorker) Progress: 36/100
(DownloadWorker) Progress: 37/100
(DownloadWorker) Progress: 38/100
(DownloadWorker) Progress: 39/100
(DownloadWorker) Progress: 40/100
(DownloadWorker) Progress: 41/100
(DownloadWorker) Progress: 42/100
(DownloadWorker) Progress: 43/100
(DownloadWorker) Progress: 44/100
(DownloadWorker) Progress: 45/100
(DownloadWorker) Progress: 46/100
(DownloadWorker) Progress: 47/100
(DownloadWorker) Progress: 48/100
(DownloadWorker) Progress: 49/100
(DownloadWorker) Progress: 50/100
(DownloadWorker) Progress: 51/100
(DownloadWorker) Progress: 52/100
(DownloadWorker) Progress: 53/100
(DownloadWorker) Progress: 54/100
(DownloadWorker) Progress: 55/100
(DownloadWorker) Progress: 56/100
(DownloadWorker) Progress: 57/100
(DownloadWorker) Progress: 58/100
(DownloadWorker) Progress: 59/100
(DownloadWorker) Progress: 60/100
(DownloadWorker) Progress: 61/100
(DownloadWorker) Progress: 62/100
(DownloadWorker) Progress: 63/100
(DownloadWorker) Progress: 64/100
(DownloadWorker) Progress: 65/100
(DownloadWorker) Progress: 66/100
(DownloadWorker) Progress: 67/100
(DownloadWorker) Progress: 68/100
(DownloadWorker) Progress: 69/100
(DownloadWorker) Progress: 70/100
(DownloadWorker) Progress: 71/100
(DownloadWorker) Progress: 72/100
(DownloadWorker) Progress: 73/100
(DownloadWorker) Progress: 74/100
(DownloadWorker) Progress: 75/100
(DownloadWorker) Progress: 76/100
(DownloadWorker) Progress: 77/100
(DownloadWorker) Progress: 78/100
(DownloadWorker) Progress: 79/100
(DownloadWorker) Progress: 80/100
(DownloadWorker) Progress: 81/100
(DownloadWorker) Progress: 82/100
(DownloadWorker) Progress: 83/100
(DownloadWorker) Progress: 84/100
(DownloadWorker) Progress: 85/100
(DownloadWorker) Progress: 86/100
(DownloadWorker) Progress: 87/100
(DownloadWorker) Progress: 88/100
(DownloadWorker) Progress: 89/100
(DownloadWorker) Progress: 90/100
(DownloadWorker) Progress: 91/100
(DownloadWorker) Progress: 92/100
(DownloadWorker) Progress: 93/100
(DownloadWorker) Progress: 94/100
(DownloadWorker) Progress: 95/100
(DownloadWorker) Progress: 96/100
(DownloadWorker) Progress: 97/100
(DownloadWorker) Progress: 98/100
(DownloadWorker) Progress: 99/100
(DownloadWorker) Progress: 100/100
(DownloadWorker) Finished at 2024/06/17 01:37:41
(MainActivity) DownloadWorker's state: ENQUEUED
(DownloadWorker) Started at 2024/06/17 01:52:41
(DownloadWorker) Progress: 0/100
(DownloadWorker) Progress: 1/100
(DownloadWorker) Progress: 2/100
(DownloadWorker) Progress: 3/100
(DownloadWorker) Progress: 4/100
(DownloadWorker) Progress: 5/100
(DownloadWorker) Progress: 6/100
(DownloadWorker) Progress: 7/100
(DownloadWorker) Progress: 8/100
(DownloadWorker) Progress: 9/100
(DownloadWorker) Progress: 10/100
(DownloadWorker) Progress: 11/100
(DownloadWorker) Progress: 12/100
(DownloadWorker) Progress: 13/100
(DownloadWorker) Progress: 14/100
(DownloadWorker) Progress: 15/100
(DownloadWorker) Progress: 16/100
(DownloadWorker) Progress: 17/100
(DownloadWorker) Progress: 18/100
(DownloadWorker) Progress: 19/100
(DownloadWorker) Progress: 20/100
(DownloadWorker) Progress: 21/100
(DownloadWorker) Progress: 22/100
(DownloadWorker) Progress: 23/100
(DownloadWorker) Progress: 24/100
(DownloadWorker) Progress: 25/100
(DownloadWorker) Progress: 26/100
(DownloadWorker) Progress: 27/100
(DownloadWorker) Progress: 28/100
(DownloadWorker) Progress: 29/100
(DownloadWorker) Progress: 30/100
(DownloadWorker) Progress: 31/100
(DownloadWorker) Progress: 32/100
(DownloadWorker) Progress: 33/100
(DownloadWorker) Progress: 34/100
(DownloadWorker) Progress: 35/100
(MainActivity) DownloadWorker's state: RUNNING
(DownloadWorker) Progress: 36/100
(DownloadWorker) Progress: 37/100
(DownloadWorker) Progress: 38/100
(DownloadWorker) Progress: 39/100
(DownloadWorker) Progress: 40/100
(DownloadWorker) Progress: 41/100
(DownloadWorker) Progress: 42/100
(DownloadWorker) Progress: 43/100
(DownloadWorker) Progress: 44/100
(DownloadWorker) Progress: 45/100
(DownloadWorker) Progress: 46/100
(DownloadWorker) Progress: 47/100
(DownloadWorker) Progress: 48/100
(DownloadWorker) Progress: 49/100
(DownloadWorker) Progress: 50/100
(DownloadWorker) Progress: 51/100
(DownloadWorker) Progress: 52/100
(DownloadWorker) Progress: 53/100
(DownloadWorker) Progress: 54/100
(DownloadWorker) Progress: 55/100
(DownloadWorker) Progress: 56/100
(DownloadWorker) Progress: 57/100
(DownloadWorker) Progress: 58/100
(DownloadWorker) Progress: 59/100
(DownloadWorker) Progress: 60/100
(DownloadWorker) Progress: 61/100
(DownloadWorker) Progress: 62/100
(DownloadWorker) Progress: 63/100
(DownloadWorker) Progress: 64/100
(DownloadWorker) Progress: 65/100
(DownloadWorker) Progress: 66/100
(DownloadWorker) Progress: 67/100
(DownloadWorker) Progress: 68/100
(DownloadWorker) Progress: 69/100
(DownloadWorker) Progress: 70/100
(DownloadWorker) Progress: 71/100
(DownloadWorker) Progress: 72/100
(DownloadWorker) Progress: 73/100
(DownloadWorker) Progress: 74/100
(DownloadWorker) Progress: 75/100
(DownloadWorker) Progress: 76/100
(DownloadWorker) Progress: 77/100
(DownloadWorker) Progress: 78/100
(DownloadWorker) Progress: 79/100
(DownloadWorker) Progress: 80/100
(DownloadWorker) Progress: 81/100
(DownloadWorker) Progress: 82/100
(DownloadWorker) Progress: 83/100
(DownloadWorker) Progress: 84/100
(DownloadWorker) Progress: 85/100
(DownloadWorker) Progress: 86/100
(DownloadWorker) Progress: 87/100
(DownloadWorker) Progress: 88/100
(DownloadWorker) Progress: 89/100
(DownloadWorker) Progress: 90/100
(DownloadWorker) Progress: 91/100
(DownloadWorker) Progress: 92/100
(DownloadWorker) Progress: 93/100
(DownloadWorker) Progress: 94/100
(DownloadWorker) Progress: 95/100
(DownloadWorker) Progress: 96/100
(DownloadWorker) Progress: 97/100
(DownloadWorker) Progress: 98/100
(DownloadWorker) Progress: 99/100
(DownloadWorker) Progress: 100/100
(DownloadWorker) Finished at 2024/06/17 01:52:41
(MainActivity) DownloadWorker's state: ENQUEUED

이하 생략

1시간 정도를 기다려, 총 4번의 작업 수행에 대한 로그 메시지를 얻어냈다. 하지만, 로그 메시지에서 보듯 PeriodicWorkRequest는 SUCCEEDED 상태 및 FAILED 상태를 가질 수 없다. PeriodicWorkRequest는 명시적으로 취소하기 전까지 무한하고 주기적으로 실행되는 작업이기 때문이다. 이 PeriodicWorkRequest가 OneTimeWorkRequest였다면 SUCCEEDED 및 FAILED 상태였겠지만 그 대신, ENQUEUED 상태로 돌아가 다시 RUNNING되기를 기다린다.

 

또, PeriodicWorkRequest는 Chaining이 불가능하기 때문에 BLOCKED 상태 또한 지닐 수 없다. Chaining에 관한 내용은 이 게시글를 봐야 이해할 수 있다.

 

#5 요약

WorkManager로 여러 작업들을 안드로이드 시스템에 맡겨놓는다.

 

#6 완성된 앱

 

android-practice/work-manager/WorkManagerBasics at master · Kanmanemone/android-practice

Contribute to Kanmanemone/android-practice development by creating an account on GitHub.

github.com

 

#7 이어지는 글

#7-1 WorkRequest에 이름 붙이고 관리하기

 

[Android] WorkManager - enqueueUniqueWork()

#1 이전 글 [Android] WorkManager - 기초#1 이전 글 [Android] WorkManager - 개요#1 WorkManager는 '지연 가능한 백그라운드 작업'의 관리자 WorkManager를 사용한 백그라운드 작업 - Kotlin | Android DevelopersAndroid에는

kenel.tistory.com

 

#7-2 Worker에 인자 전달 및 데이터 반환받기

 

[Android] WorkManager - 인자 전달 및 데이터 반환

#1 이전 글 [Android] WorkManager - 기초#1 이전 글 [Android] WorkManager - 개요#1 WorkManager는 '지연 가능한 백그라운드 작업'의 관리자 WorkManager를 사용한 백그라운드 작업 - Kotlin | Android DevelopersAndroid에는

kenel.tistory.com

 

#7-3 WorkRequest 실행에 필요한 조건 걸기

 

[Android] WorkManager - 제약 조건 (Constraints)

#1 이전 글 [Android] WorkManager - 기초#1 이전 글 [Android] WorkManager - 개요#1 WorkManager는 '지연 가능한 백그라운드 작업'의 관리자 WorkManager를 사용한 백그라운드 작업 - Kotlin | Android DevelopersAndroid에는

kenel.tistory.com

 

#7-4 작업 연쇄하기(Chaining)

 

[Android] WorkManager - 작업 연쇄하기(Chaining)

#1 이전 글 [Android] WorkManager - 기초#1 이전 글 [Android] WorkManager - 개요#1 WorkManager는 '지연 가능한 백그라운드 작업'의 관리자 WorkManager를 사용한 백그라운드 작업 - Kotlin | Android DevelopersAndroid에는

kenel.tistory.com