最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

How to use Hilt DI with WorkerManager in Android? - Stack Overflow

programmeradmin3浏览0评论

I want to use a Worker in my Android app (pure Kotlin) to so some background work. I'm using Hilt for dependency injection, but I'm facing some problems when I need to pass a custom object to the Worker.

My code is as follows:

@HiltWorker
class BackgroundWorker @AssistedInject constructor(
    @Assisted appContext: Context,
    @Assisted workerParams: WorkerParameters,
    val mockClass: MockClass
) : CoroutineWorker(appContext, workerParams) {

    init {
        Log.d("deb", "Worker: Initiated")
    }
    
    override suspend fun doWork(): Result {
        Log.d("deb", "Worker: Doing work!")
        return Result.success()
    }
}

And my MockClass is:

@Module
@InstallIn(SingletonComponent::class)
object MockModule {
    @Singleton
    @Provides
    fun provideMockClass(): MockClass = MockClass()
}

class MockClass{}

Inside my onCreate function in my main activity I call:

 WorkManager.getInstance(applicationContext).enqueue(
            OneTimeWorkRequestBuilder<BackgroundWorker>().build()
        )

to initiate the worker and call de doWork function, but when I start the app, I don't see the logs and the AppInspector shows "Failed" as the WorkerStatus.

I know that my Application class (annotated with @HiltAndroidApp) is correctly configured (using WorkerFactory, etc.) and the AndroidManifest.xml is well configured (using the provider tag, etc.), because when I comment out the line:

    val mockClass: MockClass

then I see the logs from inside my Worker (both of them, the init and the doWork one). So it works perfectly fine! But when I uncomment the line (so that the mockClass object is passed to the worker), the worker is not able to initiate.

Just for completion, here is my Manifest:

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

, Application class:

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

    override val workManagerConfiguration: Configuration
        get() = Configuration.Builder()
            .setWorkerFactory(workerFactory)
            .build()
}

, the dependencies I'm using:

[verions]
hiltCommon = "1.2.0"
workerRuntimeKtx = "2.10.0"
hilt = "2.55"
hilt-work = "1.2.0"
kotlin = "2.1.0"
ksp = "2.1.0-1.0.29"

[libraries]
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" }
hilt-work = { group = "androidx.hilt", name = "hilt-work", version.ref = "hilt-work" }
androidx-hilt-common = { group = "androidx.hilt", name = "hilt-common", version.ref = "hiltCommon" }
androidx-worker-runtime-ktx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "workerRuntimeKtx" }

[plugins]
hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
kotlin-ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }

in module-level build.gradle:

plugins{
    ...
    alias(libs.plugins.hilt)
    alias(libs.plugins.kotlin.ksp)
}
dependencies{
    implementation(libs.androidx.worker.runtime.ktx)
    implementation(libs.hilt.android)
    implementation(libs.hilt.work)
    implementation(libs.androidx.hiltmon)
    ksp(libs.hiltpiler){
        exclude("META-INF/gradle/incremental.annotation.processors")
    }
}

and in project-level build.gradle:

plugins{
    alias(libs.plugins.kotlin.ksp) apply false
    alias(libs.plugins.hilt) apply false
}

I think my problem is somehow related to the DI and Hilt, but I cannot figure out what it is. I use Hilt for dependency injection on other parts in my app, and they work okay.

I want to use a Worker in my Android app (pure Kotlin) to so some background work. I'm using Hilt for dependency injection, but I'm facing some problems when I need to pass a custom object to the Worker.

My code is as follows:

@HiltWorker
class BackgroundWorker @AssistedInject constructor(
    @Assisted appContext: Context,
    @Assisted workerParams: WorkerParameters,
    val mockClass: MockClass
) : CoroutineWorker(appContext, workerParams) {

    init {
        Log.d("deb", "Worker: Initiated")
    }
    
    override suspend fun doWork(): Result {
        Log.d("deb", "Worker: Doing work!")
        return Result.success()
    }
}

And my MockClass is:

@Module
@InstallIn(SingletonComponent::class)
object MockModule {
    @Singleton
    @Provides
    fun provideMockClass(): MockClass = MockClass()
}

class MockClass{}

Inside my onCreate function in my main activity I call:

 WorkManager.getInstance(applicationContext).enqueue(
            OneTimeWorkRequestBuilder<BackgroundWorker>().build()
        )

to initiate the worker and call de doWork function, but when I start the app, I don't see the logs and the AppInspector shows "Failed" as the WorkerStatus.

I know that my Application class (annotated with @HiltAndroidApp) is correctly configured (using WorkerFactory, etc.) and the AndroidManifest.xml is well configured (using the provider tag, etc.), because when I comment out the line:

    val mockClass: MockClass

then I see the logs from inside my Worker (both of them, the init and the doWork one). So it works perfectly fine! But when I uncomment the line (so that the mockClass object is passed to the worker), the worker is not able to initiate.

Just for completion, here is my Manifest:

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

, Application class:

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

    override val workManagerConfiguration: Configuration
        get() = Configuration.Builder()
            .setWorkerFactory(workerFactory)
            .build()
}

, the dependencies I'm using:

[verions]
hiltCommon = "1.2.0"
workerRuntimeKtx = "2.10.0"
hilt = "2.55"
hilt-work = "1.2.0"
kotlin = "2.1.0"
ksp = "2.1.0-1.0.29"

[libraries]
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" }
hilt-work = { group = "androidx.hilt", name = "hilt-work", version.ref = "hilt-work" }
androidx-hilt-common = { group = "androidx.hilt", name = "hilt-common", version.ref = "hiltCommon" }
androidx-worker-runtime-ktx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "workerRuntimeKtx" }

[plugins]
hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
kotlin-ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }

in module-level build.gradle:

plugins{
    ...
    alias(libs.plugins.hilt)
    alias(libs.plugins.kotlin.ksp)
}
dependencies{
    implementation(libs.androidx.worker.runtime.ktx)
    implementation(libs.hilt.android)
    implementation(libs.hilt.work)
    implementation(libs.androidx.hiltmon)
    ksp(libs.hiltpiler){
        exclude("META-INF/gradle/incremental.annotation.processors")
    }
}

and in project-level build.gradle:

plugins{
    alias(libs.plugins.kotlin.ksp) apply false
    alias(libs.plugins.hilt) apply false
}

I think my problem is somehow related to the DI and Hilt, but I cannot figure out what it is. I use Hilt for dependency injection on other parts in my app, and they work okay.

Share Improve this question edited Mar 21 at 17:14 Pion Developer asked Mar 20 at 20:23 Pion DeveloperPion Developer 2114 silver badges12 bronze badges 0
Add a comment  | 

1 Answer 1

Reset to default 1

Your Gradle setup for Hilt is off.

In your version catalog you need to replace the two libraries

hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" }
androidx-hilt-common = { group = "androidx.hilt", name = "hilt-common", version.ref = "hiltCommon" }

with these:

hilt-android-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" }
androidx-hilt-compiler = { group = "androidx.hilt", name = "hilt-compiler", version.ref = "hilt-work" }

Now, in your gradle file replace

implementation(libs.androidx.hiltmon)
ksp(libs.hiltpiler){
    exclude("META-INF/gradle/incremental.annotation.processors")
}

accordingly with

ksp(libs.hilt.androidpiler)
ksp(libs.androidx.hiltpiler)

The Hilt injection should now work without issues, even for the WorkManager.

发布评论

评论列表(0)

  1. 暂无评论