이번에 진행하는 프로젝트에서 FCM이 날라왔을 때, 서버에 현재 유저의 위치를 보내야하는 기능이 있어야 해서, 위젯으로 하는게 좋을까 아님 Service를 이용해야 하나 고민이 많았는데, Jetpack에 WorkManager가 있는 것을 보고 아! 이거다. 하고 바로 공부를 진행했다. 아직 어떻게 써야 할지 감은 잘 안잡히지만 ,실제 코드로 적용해본 것은 기능 완성하면서 작성할 계획이다.
WorkManager란
WorkManager는 Jetpack의 구성요소로, 백그라운드 처리에 권장되는 기본 API이다.
즉, 기존에 서비스에서 할 수 있는 작업을 WorkManager를 활용하여 수행할 수 있다.
그럼 기존에 사용하던 서비스를 사용하면 되지 않냐?
그렇기엔 서비스에 백그라운드 제약이 생기고, FCM이 왔을 때(= 특정 이벤트)에 대해 유휴 상태의 앱을 깨워야 하는 상황 등을 고려했을 때, WorkManager를 사용하는 것을 고려했다.
또한 공식 문서에서 FirebaseJobDispatcher, GcmNetworkManager, JobScheduler 등의 백그라운드 예약 API 대체할 것을 권장하니 꼭 써봐야지!
백그라운드 제약
안드로이드 8버전(API Level 26)이상 부터 백그라운드 작업에 제약이 생겼다.
1. Background 위치 사용 제한
-> 배터리 사용을 줄이기 위해 백그라운드에서 사용자의 현재 위치를 검색할 수 있는 빈도를 제한했다.
2. 앱이 백그라운드로 가게 되면, 몇 분 정도의 허용시간만 주고 시스템에서 백그라운드 서비스를 바로 종료시킨다. ***
3. Activity를 시작하기 위해 Foreground Service를 실행하는 앱은 Background에 있는 것으로 간주한다.
WorkManager 기능
1. 작업 제약 조건
네트워크 연결 상태, 배터리가 충분할 때만 실행하는 등 최적의 조건을 선택하여 작업을 실행할 수 있다.
2. 다양한 작업 유형
OneTimeWorkRequestBuilder()를 통해 한 번만 작업을 실행하도록 할 수 있거나,
PeriodicWorkRequestBuilder()로 특정 시간에 주기적으로 작업을 실행하도록 할 수 있다.
3. 작업에 대한 모니터링
WorkManager는 작업의 완료 및 실패 등에 대한 알림을 제공하기 때문에 이에 대해 적절하게 대처 할 수 있도록 한다.
4. 체인으로 작업을 연결
메소드를 통해 체인으로 연결된 작업을 수행할 수 있어, 순차적으로 진행해야 하는 작업을 처리하기에 용이하다.
5. LiveData 사용
Worker와 LiveData를 합쳐 작업의 결과를 observe할 수 있다. 데이터 관찰이 있어서, 작업 처리할 때 굉장이 유용할듯하다.
WorkManager 컴포넌트
WorkManager의 구성은 위의 그림과 같다.
대략 중요한 것들을 정리하자면
1. Worker
2. WorkRequest
3. WorkManager
Worker
public abstract class Worker extends ListenableWorker {
public Worker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
**
@WorkerThread
public abstract @NonNull Result doWork();
}
Worker 클래스의 경우 추상클래스로 상속을 통해 구현해야 한다.
여기서 처리해야 하는 백그라운드 작업의 코드들을 doWork() 메서드를 오버라이드 하고,
doWork()에 작성하면 된다.
doWork()에 경우 위의 코드와 같이 Result 값을 반환해야 하는데
Success, Retry, Failure로 반환할 수 있다.
대략, 이런 느낌
class ExampleWorker(context : Context, workerParams : WorkerParameters)
: Worker(context, workParams){
override fun doWork() : Result{
//백그라운드 처리 코드
return Result.success()
}
}
WorkRequest
WorkManager를 통해 실제 요청하는 작업들이다.
처리해야 하는 작업과, 작업에 실행 조건 및 제약 사항 등 작업을 실행하는데 있어서 전반적인 정보들을 여기에서 설정해준다.
=> 즉, 언제 어떻게 작업이 실행되어야 하는지를 정의해준다.
맨 위에서 언급한 것처럼 반복 여부는 OneTimeWorkRequest와 PeriodicWorkRequest로 나눌 수 있다.
-> OneTimeWorkRequest
val exampleWorkRequest : WorkRequest =
OneTimeWorkRequestBuilder<UploadWorker>()
.build()
일회성 작업의 경우 다음과 같이 진행된다.
작업이 실행되고자 하는 시점에 ENQUEUED 상태에서 RUNNING 상태로 이동하고 작업 결과에 따라 각각의 상태값을 반환한다.
-> PeriodicWorkRequest
val exampleWorkRequst = PeriodicWorkRequest
.Builder(ExampleWorker::class.java, 10, TimeUnit.MINUTES)
.build()
10분의 한번씩 작업이 실행되도록 할 수 있다.
주기적인 작업은 다음과 같이 진행된다.
일회성 작업에는 성공이나 실패 상태를 적용할 수 있지만, 주기적인 작업에서는 CANCELLED만 있다고 한다. 얘는 종료가 없기 때문!
또한 WorkRequest에서는 제약 사항을 걸 수 있다.
Constraints.Builder() 에 원하는 제약을 걸어주고 build() 한뒤
이를 workRequest에 setConstraints로 걸어주면 된다!
//네트워크가 연결된 상태에서만 실행
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
val exampleWorkRequest = OneItemWorkRequestBuilder<ExampleWorker>()
.setConstraints(constraints)
.build()
WorkManager
위의 그림과 같이 처리 해야 하는 작업을 자신의 큐에 넣고 관리 하는 역할을 한다.
싱글톤으로 구현이 되어 있어 getInstance()로 WorkManager의 인스턴스를 받아서 사용한다.
Configuration
초기화를 활용해 WorkManager를 Custom 하기 위해 사용 한다.
즉, 작업을 관리하고 예약하는 방법을 내가 원하는대로 설정하기 위해 얘를 활용한다.
위에서 만들어 놓은 Worker와 WorkRequest를 WorkManager에 enqueue()로 넣어주면 된다.
val exampleWorkRequest : WorkRequest = OneTimeWorkRequestBuilder<ExampleWorker>().build()
WorkManager.getInstance(this).enqueue(exampleWorkRequest)
나는 이것을 FCM 알림이 올때 onMessageReceived에 넣어줬다.
대략적인 부분은 정리했는데, 계속 공부하면서 적용한 내용들은 추가할 계획이다!
https://android-developer.tistory.com/16
https://fornewid.medium.com/workmanager-정리-62e9f6f53767
'Android > Android Jetpack' 카테고리의 다른 글
[Android] Jetpack - (4) Room (0) | 2025.03.04 |
---|---|
[Android] Jetpack - (3) Paging3 (1) | 2024.12.01 |
[Android] Jetpack - (1) ViewModel (0) | 2024.07.11 |