WorkManager hilt not working

강현석·2023년 1월 10일
0

troubleshooting

목록 보기
2/7

Use Hilt with other Jetpack libraries | Android Developer
위 링크를 참고하면, WorkManager에 hilt를 적용할 수 있다.

WorkManager + Hilt 적용

1. 디펜던시 추가

implementation("androidx.hilt:hilt-work:1.0.0")

디펜던시를 추가하면 WorkManager와 관련된 annotation을 사용할 수 있다.

2. WorkManagerConfiguration 설정

Application 클래스에 아래 내용을 추가한다.

class MyApplication : Application(), Configuration.Provider {
    @Inject
    lateinit var workFactory: HiltWorkerFactory

    override fun getWorkManagerConfiguration(): Configuration =
    	Configuration.Builder()
            .setWorkerFactory(workerFactory)
            .build()

Application단에서 주입받은 HiltWorkerFactory를 활용하여 WorkManagerConfiguration을 만들어준다.

3. Worker 구현

@HiltWorker
class PingWorker @AssistedInject constructor(
    @Assisted appContext: Context,
    @Assisted workerParams: WorkerParameters,
    private val sendPingUseCase: SendPingUseCase
) : CoroutineWorker(appContext, workerParams) {

    override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
        sendPingUseCase.execute()
            .let {
                if (it.isSuccess) Result.success() else Result.failure()
            }
    }
}

WorkManager를 통해서 서버에 ping을 쏘도록 구현해보았다.
ping을 보내는 API가 RESTful API이여서 CoroutineWorker를 사용했다.
이렇게 하면 일단 끝이다.

과연 끝일까?

무엇을 놓쳤을까?

Default initializer 제거

가이드 문서의 마지막에 아래와 같은 내용이 있다.

Note: Because this customizes the WorkManager configuration, you also must remove the default initializer from the AndroidManifest.xml file as specified in the WorkManager docs.

요약해보자면, WorkManager에 Hilt를 적용하기 위해 custom configuration을 만들었기 때문에 기본 초기자를 제거해야한다는 의미이다.
제거해주지 않으면 WorkManager가 동작하지 않는다.
Custom WorkManager Configuration and Initialization | Android Developer
위 링크를 참고하여 기본 초기자를 제거해보자.

AndroidManifest에, 프로젝트에서 App Startup 라이브러리를 쓰고 있다면 아래와 같이 추가한다.

 <provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities="${applicationId}.androidx-startup"
    android:exported="false"
    tools:node="merge">
    <!-- If you are using androidx.startup to initialize other components -->
    <meta-data
        android:name="androidx.work.WorkManagerInitializer"
        android:value="androidx.startup"
        tools:node="remove" />
 </provider>

App Startup 라이브러리를 쓰고 있지 않다면 아래와 같이 추가하면 된다.

 <provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities="${applicationId}.androidx-startup"
    tools:node="remove">
 </provider>

하지만 work-runtime-ktx 버전이 2.6 미만이라면 아래와 같이 추가하면 된다.

<provider
    android:name="androidx.work.impl.WorkManagerInitializer"
    android:authorities="${applicationId}.workmanager-init"
    tools:node="remove" />

work-runtime-ktx 버전이 2.6 이상인 경우에는, WorkManager 내부 구현체가 App Startup 라이브러리를 사용하고 있다고 한다.

Since WorkManager 2.6, App Startup is used internally within WorkManager. To provide a custom initializer you need to remove the androidx.startup node.

그리고 ${applicationId}는 있는 그대로 써야 한다.
진짜 applicationId(예, com.sample.helloworld)를 적는 것이 아니다.

hilt-compiler 디펜던시 추가

대부분 WorkManager에 hilt를 적용하는 이유가, 프로젝트 구조가 hilt 기반으로 되어있을 것이다.
그래서 hilt-work 디펜던시만 추가할 것이고, 실제로 구현을 완료하고 빌드도 잘 된다.
하지만 실행해보면 WorkManager가 동작하지 않는다.
반드시 아래 부분을 추가해주어야 한다.

kapt("androidx.hilt:hilt-compiler:1.0.0")

dagger-hilt가 적용되어 있으면, hilt-compiler가 gradle에 추가되어 있어서 놓치기 쉽다.
자세히 보면 다르다.

  • androidx.hilt:hilt-compiler
  • com.google.dagger:hilt-android-compiler

이렇게까지 하면 잘 동작할 것이다.

profile
볼링을 좋아하는 안드로이드 개발자

0개의 댓글