dagger: Cannot Inject Coroutine Worker With Hilt

I am using Hilt With Coroutine Worker , I am getting this error when work is being dispatched ! I have searched for this issue but couldn’t find a solution , any help would be appreciated !

Error

E/WM-WorkerFactory: Could not instantiate com.wakaztahir.timeline.utils.workers.NotificationSetupWorker
    java.lang.NoSuchMethodException: com.wakaztahir.timeline.utils.workers.NotificationSetupWorker.<init> [class android.content.Context, class androidx.work.WorkerParameters]
        at java.lang.Class.getConstructor0(Class.java:2332)
        at java.lang.Class.getDeclaredConstructor(Class.java:2170)
        at androidx.work.WorkerFactory.createWorkerWithDefaultFallback(WorkerFactory.java:95)
        at androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.java:244)
        at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:136)
        at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:91)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:923)
E/WM-WorkerWrapper: Could not create Worker com.wakaztahir.timeline.utils.workers.NotificationSetupWorker

Application Class

@HiltAndroidApp
class TimelineApp : Application(), Configuration.Provider {

    @Inject
    lateinit var workerFactory: HiltWorkerFactory
    
    override fun getWorkManagerConfiguration() =
        Configuration.Builder()
            .setWorkerFactory(workerFactory)
            .build()

}

Here’s the actual Worker constructor

@HiltWorker
class NotificationSetupWorker @AssistedInject constructor(
    @Assisted val context: Context,
    @Assisted workerParams: WorkerParameters,
    val reminderDao: ReminderDao
) : CoroutineWorker(context, workerParams)

Gradle

Project Level :

classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" // hilt_version = 2.35.1 & kotlin_version = 1.4.32

App Level :

plugins {
    id 'kotlin-kapt'
    //Hilt Plugin
    id 'dagger.hilt.android.plugin'
}
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-compiler:$hilt_version"
implementation 'androidx.hilt:hilt-work:1.0.0'
kapt 'androidx.hilt:hilt-compiler:1.0.0'

//Work Manager
def work_version = "2.6.0-alpha02"
implementation "androidx.work:work-runtime-ktx:$work_version"
implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'

https://stackoverflow.com/questions/67388068/injecting-coroutineworker-with-hilt-could-not-instantiate-woker

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 32 (1 by maintainers)

Most upvoted comments

Hi, thanks for sharing. Think i had same issue there. I am interested in hearing your feedback @forntoh 😃

On my side i follow this stackoverflow answer and that’s correct, for me it was a dependencies issue.

I forgot to add

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

only have

kapt("com.google.dagger:hilt-android-compiler:2.38.1")

So, here the complete depencies part fort Hilt, Work and Coroutines

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.1'

implementation "com.google.dagger:hilt-android:2.38.1"
kapt "com.google.dagger:hilt-android-compiler:2.38.1"
implementation("androidx.hilt:hilt-work:1.0.0")
kapt("androidx.hilt:hilt-compiler:1.0.0")

implementation "androidx.work:work-runtime:2.6.0"
implementation "androidx.work:work-runtime-ktx:2.6.0"

It can be a little messy to deal with all those depencies but we are targeting many purpose that worth the effort. 😊

Hi, I solve this problem workmanager version 2.7.1 hilt version 2.38.1

in my solution, i create custom workerFactory

class MyWorkerFactory @Inject constructor(private val repository: Repository) : WorkerFactory() {
    override fun createWorker(
        appContext: Context,
        workerClassName: String,
        workerParameters: WorkerParameters
    ): ListenableWorker = MyWorker(appContext, workerParameters, repository)
}

in Application class

@HiltAndroidApp
class MainApplication : Application(), Configuration.Provider {
    @Inject
    lateinit var myWorkerFactory: MyWorkerFactory

   override fun getWorkManagerConfiguration(): Configuration = Configuration.Builder()
        .setMinimumLoggingLevel(android.util.Log.DEBUG)
        .setWorkerFactory(myWorkerFactory)
        .build()
}

in MyWorker

@HiltWorker
class MyWorker @AssistedInject constructor(
    @Assisted appContext: Context,
    @Assisted workerParameters: WorkerParameters,
    private val repository: Repository
) : RxWorker(appContext, workerParameters) {
    override fun createWork(): Single<Result> {
        val id = inputData.getInt(PaymentLimitReceiver.ID_ORDER, 0)
        return repository.cancelOrder(id)
            .map {
                Result.success()
            }
            .doOnError {
                Result.retry()
            }
    }

}

in Manifest add this provider

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

I’ve fixed the issue

Since using work manager version above than 2.6.0-alpha01 , Work Manager version above 2.6.0-alpha01 uses startup initializer Read Here

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

https://stackoverflow.com/questions/67388068/injecting-coroutineworker-with-hilt-could-not-instantiate-woker did the trick !

So I was able to resolve this by changing my app module to this

@Module
@InstallIn(SingletonComponent::class)
object WorkManagerInitializer: Initializer<WorkManager> {
  @Provides
  @Singleton
  override fun create(@ApplicationContext context: Context): WorkManager {
    val entryPoint = EntryPointAccessors.fromApplication(
      context,
      WorkManagerInitializerEntryPoint::class.java
    )
    val configuration = Configuration
      .Builder()
      .setWorkerFactory(entryPoint.hiltWorkerFactory())
      .setMinimumLoggingLevel(if (BuildConfig.DEBUG) Log.DEBUG else Log.INFO)
      .build()

    WorkManager.initialize(context, configuration)
    return WorkManager.getInstance(context)
  }

  override fun dependencies(): MutableList<Class<out Initializer<*>>> {
    return mutableListOf()
  }

  @InstallIn(SingletonComponent::class)
  @EntryPoint
  interface WorkManagerInitializerEntryPoint {
    fun hiltWorkerFactory(): HiltWorkerFactory
  }
}```
Then in my view model, I can set it up like the following 
`@HiltViewModel
class AuthenticationViewModel @Inject constructor(
  private val workManager: WorkManager,
): ViewModel() {}`

Then enqueue it
`workManager.enqueueUniquePeriodicWork(Constants.UPDATE_CACHE_WORKER, ExistingPeriodicWorkPolicy.UPDATE, request)`

This provider is only for WorkManager version above than 2.6.0-alpha01 so I would suggest you to update WorkManger and see if it works

Wrong :

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

Correct :

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

Same situation here @davidhowe were you able to resolve this?

After a day of trying all alternative options, changing versions, I too cannot resolve issue. I can also replicate this same issue on googles sunflower app using latest versions.

Versions:

hilt_version = '2.43.2'
work_version = '2.8.0-alpha04'
// Project dependency
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
// App dependencies
// hilt (DI)
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
implementation("androidx.hilt:hilt-work:1.0.0")
kapt("androidx.hilt:hilt-compiler:1.0.0")
// Workmanager
implementation "androidx.work:work-runtime:$work_version"
implementation "androidx.work:work-runtime-ktx:$work_version"

Provider in manifest:

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

Worker:

@HiltWorker
class CustomerSyncWorker @AssistedInject constructor(
    @Assisted appContext: Context,
    @Assisted workerParams: WorkerParameters,
    private val fetchCustomersUseCase: FetchCustomersUseCase,
) : CoroutineWorker(appContext, workerParams) {

App class:

@HiltAndroidApp
class BambaApplication : Application(), Configuration.Provider {

    @Inject
    lateinit var workerFactory: HiltWorkerFactory

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

Hi @wakaztahir, I am using workmanager 2.6.0 and I was using Hilt androidx.hilt:hilt-work:1.0.0 to use @HiltWorker to inject fields into my worker. As long as I am using only the default params (context and workerparams) its working fine, but as soon as I add any custom fields I am getting error like:

2021-09-07 16:36:00.507 24441-26679/com.xxx.xxxx E/WM-WorkerFactory: Could not instantiate com.xxx.xxxx.workmanagers.DataSyncWorker
    java.lang.NoSuchMethodException: com.xxx.xxxx.workmanagers.DataSyncWorker.<init> [class android.content.Context, class androidx.work.WorkerParameters]
        at java.lang.Class.getConstructor0(Class.java:2332)
        at java.lang.Class.getDeclaredConstructor(Class.java:2170)
        at androidx.work.WorkerFactory.createWorkerWithDefaultFallback(WorkerFactory.java:95)
        at androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.java:244)
        at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:136)
        at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:91)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:923)
2021-09-07 16:36:00.507 24441-26679/com.xxx.xxxx E/WM-WorkerWrapper: Could not create Worker com.xxx.xxxx.workmanagers.DataSyncWorker

For those who still have trouble despite following the steps above, the line below apparently solved the problem:

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

@forntoh I have edited my answer because your provider in the manifest was incorrect , Please update it , I didn’t notice it before and also update your work manager version to greater than 2.6.0-alpha 01 @abhriyaroy Please check your work manager provider , does it exactly match with the given above !

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

I actually switched to what you see here because the correct one wasn’t working 😃. Anyways, I have fixed the issue. I’ll post my solution soon.

==> AndroidManifest:

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

==> Application Class:

@entrypoint @Installin(SingletonComponent::class) interface HiltWorkerFactoryEntryPoint { fun workerFactory(): HiltWorkerFactory }

override fun getWorkManagerConfiguration() =
    Configuration.Builder()
        .setExecutor(Dispatchers.Default.asExecutor())
        .setWorkerFactory(EntryPoints.get(this, HiltWorkerFactoryEntryPoint::class.java).workerFactory())
        .setTaskExecutor(Dispatchers.Default.asExecutor())
        .build()

=> Application onCreate() { WorkManager.initialize(this, workManagerConfiguration) }

Finally getting success above code. Now initialize workmanager perfectly.

Creating CUSTOM WORKER-FACTORY was the only thing that worked for me. Got the bug in prod, and fixed after several days. this helped a lot. @Himanshu-381 hiltVersion = “2.44.2” workVersion = “2.8.0”

==> AndroidManifest:

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

==> Application Class:

@EntryPoint @InstallIn(SingletonComponent::class) interface HiltWorkerFactoryEntryPoint { fun workerFactory(): HiltWorkerFactory }

override fun getWorkManagerConfiguration() =
    Configuration.Builder()
        .setExecutor(Dispatchers.Default.asExecutor())
        .setWorkerFactory(EntryPoints.get(this, HiltWorkerFactoryEntryPoint::class.java).workerFactory())
        .setTaskExecutor(Dispatchers.Default.asExecutor())
        .build()

=> Application onCreate() { WorkManager.initialize(this, workManagerConfiguration) }

Finally getting success above code. Now initialize workmanager perfectly.

Make sure you initialize your WorkManager get getting an instance and not use WorkManager.initialize(applicationContext, config).

val constraints = Constraints.Builder()
               .setRequiredNetworkType(NetworkType.CONNECTED)
               .setRequiresBatteryNotLow(false)
               .build()

           val work = PeriodicWorkRequestBuilder<MyWorker>(15, TimeUnit.MINUTES)
               .setConstraints(constraints)
               .build()

           WorkManager.getInstance(applicationContext).enqueue(work)

None of the solutions helped me, still seeing the same problem. Dagger version 2.42.3, using these dependencies:

implementation "androidx.work:work-runtime-ktx:2.7.1"
implementation 'androidx.hilt:hilt-work:1.0.0'
implementation "com.google.dagger:hilt-android:2.42.3"
implementation 'androidx.hilt:hilt-navigation-compose:1.0.0'
kapt "com.google.dagger:hilt-compiler:2.42.3"
kapt 'androidx.hilt:hilt-compiler:1.0.0'

The following in AndroidManifest.xml, inside application:

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

My application class:

@HiltAndroidApp
class App : Application(), Configuration.Provider {
    @Inject
    lateinit var workerFactory: HiltWorkerFactory
    
    override fun getWorkManagerConfiguration(): Configuration {
        return Configuration.Builder() // This does get called, breakpoints here stop
            .setWorkerFactory(workerFactory)
            .build()
    }
}

The worker:

@HiltWorker
class EnrolWorker @AssistedInject constructor(
    @Assisted appContext: Context,
    @Assisted workerParams: WorkerParameters,
    private val getBestFacility: GetBestFacilityUseCase,
) : CoroutineWorker(appContext, workerParams)

This happens using compose 1.3.0-beta02, kotlin 1.7.10, gradle plugin 7.3.0-rc01

Perhaps also worthy of note, I have the app package moved to build.gradle inside the android scope, but adding it back to AndroidManifest.xml did not make a difference, replacing ${applicationId} with my actual package name did not help either

Hi @forntoh did you find anything to make it work?

I fixed it, but I can’t even remember what I did, I will take a look at my code and update this thread later.