Closed Pezcraft closed 10 months ago
One thing that strikes me a bit odd is that your have implementation(libs.hilt.plugin)
which I understand as your project depending on the Hilt Gradle plugin as if it was a library with APIs to be used in your project but thats not quite how a Gradle Plugin is applied. Can you confirm you are indeed applying the plugin as described in https://dagger.dev/hilt/gradle-setup.html, either with the apply plugin
syntax or the newer plugins
DSL.
In essence HiltWorkerFactory
is a multibinding of all @HiltWorker
annotated so if you debug and breakpoint inside the factory you should see a map where you can confirm if the worker is in the map a signal that the multibinding module was picked up and generated. If you don't see it then either the @InstallIn
module based of the @HiltWorker
is not being generated or the multibinding is not being discovered because it is not a direct dependency of the app module or it is a transitive dependency but the Hilt Gradle Plugin which does aggregation is not being applied.
I am applying the plugin like this... root build.gradle
buildscript {
repositories {
google()
mavenCentral()
jitpack()
}
dependencies {
classpath(libs.kotlingradleplugin)
classpath(libs.gradleplugin)
classpath(libs.play.services)
classpath(libs.undercouch.download)
classpath(libs.firebase.plugins)
classpath(libs.hilt.plugin)
classpath(libs.firebase.crashlytics.gradle)
classpath(libs.paparazzi.gradle)
}
}
plugins {
id("com.google.dagger.hilt.android") version "2.44.2" apply false
}
And in :app
and :core-ble
module...
plugins {
id("com.android.application") //this is just in :app
id("com.android.library")
id("org.jetbrains.kotlin.android")
id("kotlin-kapt")
id("kotlin-parcelize")
id("dagger.hilt.android.plugin")
id("com.google.dagger.hilt.android")
}
I debugged HiltWorkerFactory
and the map is empty. So how can this be fixed in feature modules?
Can you please clarify if :core-ble
is a feature module as described in https://developer.android.com/guide/playcore/feature-delivery? If that is the case, then sadly having a Hilt worker in such module is not supported as those modules cannot be correctly aggregated as described in https://developer.android.com/training/dependency-injection/hilt-multi-module#dfm
If it is just a library module, as in a Gradle module, then can you try having :app
directly depend on :core-ble
?
Sorry it's not. It's just a module implemented by :app
I ended up writing my own WorkerFactory and injecting the necessary parameters there...
class BleWorkerFactory @Inject constructor(
private val bleServiceModule: BleServiceModule,
) : WorkerFactory() {
override fun createWorker(appContext: Context, workerClassName: String, workerParameters: WorkerParameters): ListenableWorker? {
return when (workerClassName) {
RemoteConfigSyncWorker::class.java.name -> RemoteConfigSyncWorker(appContext, workerParameters)
HardwareReportWorker::class.java.name -> HardwareReportWorker(appContext, workerParameters, bleServiceModule)
ActivitySyncWorker::class.java.name -> ActivitySyncWorker(appContext, workerParameters, bleServiceModule)
else -> null
}
}
}
@Singleton
class MyDelegatingWorkerFactory @Inject constructor(
bleWorkerFactory: BleWorkerFactory
) : DelegatingWorkerFactory() {
init {
addFactory(bleWorkerFactory)
}
}
In my application I do not implement Configuration.Provider since I got a RuntimeException: Unable to instantiate application
when overriding the workManagerConfiguration val. Instead I set the configuration in onCreate().
@HiltAndroidApp
open class RandomHiltApplication : MyApplication() {
@EntryPoint
@InstallIn(SingletonComponent::class)
interface WorkerFactoryEntryPoint {
fun workerFactory(): MyDelegatingWorkerFactory
}
override fun onCreate() {
val workManagerConfiguration: Configuration = Configuration.Builder()
.setWorkerFactory(EntryPoints.get(this, WorkerFactoryEntryPoint::class.java).workerFactory())
.setMinimumLoggingLevel(Log.VERBOSE)
.build()
WorkManager.initialize(this, workManagerConfiguration)
super.onCreate()
}
}
My Fastlane builds are now working and I am happy with it. Sadly, I couldn't find out, why the HiltWorkerFactory is not working.
This is the only working suggestion. Thank you @Pezcraft
I get the following exception for 2 of my CoroutineWorkers with additional parameters injected by Hilt. This does not happen for workers without additional parameters and only happens when I install the app via APK by my fastlane build. Android Studio builds work perfectly. But my build pipeline uses the same settings as Android Studio builds. By work, I mean that the workers get enqueued and do not throw the following exception...
The title of this issue already states that the internal variable
mWorkerFactories
is empty. My worker cannot be found then. But with Android Studio builds it's not empty. Before I continue. What makes this question different from other similar ones is, that I have a multi-module project. Maybe I am missing something because of it.This is the Worker inside the app module
:core-ble
This worker gets enqueued always, but has no additional injected parameters. Because of reflection, it can be found.
As you see in my Manifest, I removed the default Initializer and added my own...
This is the new Initializer...
I do this in onCreate of my MultiDexApplication which is located in
:app
My imports... (in both
:core-ble
and:app
.I also tried adding these ProGuard rules, but why should it work with Android Studio builds but not with APK builds.
This is my hilt module for one of the parameters of the WorkManagers. Same for the parameters inside
provideBleServiceModule