Dependency injection inside BroadcastReceiver
using Hilt isn't working. I try to invoke a BroadcastReceiver
using an alarm from MainActivity
and i am getting UninitializedPropertyAccessException
. According to the documentation it should be as simple as adding the @AndroidEntryPoint
annotation to the receiver but its not.
Sample Code:
App.kt:
@HiltAndroidApp
class App: Application() {
override fun onCreate() {
super.onCreate()
Log.d(App::class.simpleName, "onCreate: Application")
}
}
TestHiltInjection.kt:
class TestHiltInjection @Inject constructor() {
operator fun invoke() {
Log.d(TestHiltInjection::class.java.simpleName, "invoke called.")
}
}
HiltBroadcastReceiver.kt:
@AndroidEntryPoint
class HiltBroadcastReceiver : BroadcastReceiver() {
@Inject lateinit var testHiltInjection: TestHiltInjection
override fun onReceive(context: Context?, intent: Intent?) {
testHiltInjection()
}
}
MainActivity.kt:
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val manager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val pending = PendingIntent
.getBroadcast(this, 0, Intent(this, HiltBroadcastReceiver::class.java), 0)
manager.setInexactRepeating(
AlarmManager.ELAPSED_REALTIME_WAKEUP,
15000, 15000,
pending
)
}
}
Output Logcat:
kotlin.UninitializedPropertyAccessException: lateinit property testHiltInjection has not been initialized
Update
Issue was already solved on 2.29.1 version, just use @AndroidEntryPoint
As I mentioned before Dagger/Hilt has a significant impact on build time due to code generation. On the other hand, Koin also affects time, but not build, but runtime. Koin has slightly worse runtime performance, because it resolves dependencies at runtime.
Hilt provides a standard way to incorporate Dagger dependency injection into an Android application. The goals of Hilt are: To simplify Dagger-related infrastructure for Android apps. To create a standard set of components and scopes to ease setup, readability/understanding, and code sharing between apps.
In Dagger, we create scope annotations such as ActivityScope, FragmentScope to specify the lifecycle, but hilt provides us with core components such as Application, Activity, Fragment, Service, and View.
In order to do so, Go to app > java > package > Right-click > New > Kotlin Class/File and create a new class and name it as MainViewModel. kt. We will annotate it with @HiltViewModel which makes the models to be created using Hilt's model factory that makes it easier to be used with Activities and Fragments.
Update: According to the issue the problem should be fixed in version 2.29.1 of Dagger Hilt. So, just use version 2.29.1-alpha
or above. Don't forget to update hilt-android-gradle-plugin
version as well.
Original answer: There's a GitHub issue and a workaround. It seems that injection doesn't work because it actually happens inside onReceive()
method of the generated parent class. The problem is that you cannot call the super method since it's abstract. But you can create a simple wrapper class that fixes the problem:
abstract class HiltBroadcastReceiver : BroadcastReceiver() {
@CallSuper
override fun onReceive(context: Context, intent: Intent) {}
}
@AndroidEntryPoint
class MyBroadcastReceiver : HiltBroadcastReceiver() {
@Inject lateinit var testHiltInjection: TestHiltInjection
override fun onReceive(context: Context?, intent: Intent?) {
super.onReceive(context, intent) // <-- it's the trick
...
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With