How to inject into a BroadcastReceiver
Does someone already had to inject an already existing class, with some business logic, into a BroadcastReceiver using dagger?
I'm using dagger 1 and already found a nice example (https://github.com/adennie/fb-android-dagger) but, I could not find how we can add an already existing class, which belongs to a different module, into a BroadcastReceiver.
Any help or advice would be greatly appreciated.
Same as you inject to an Activity
public void onReceive(Context context, Intent intent) {
((Application) context.getApplicationContext()).getInjector().inject(this);
}
Dagger 2 example for injecting objects into a BroadcastReceiver.
The BroadcastReceiverModule.kt
@Module
abstract class BroadcastReceiverModule {
@ContributesAndroidInjector
abstract fun contributesMyTestReceiver() : MyTestReceiver
}
The AppComponent.kt
@Singleton
@Component(
modules = [
(AndroidSupportInjectionModule::class),
(BroadcastReceiverModule::class)
])
interface AppComponent : AndroidInjector<MyApp> {
@Component.Builder
abstract class Builder : AndroidInjector.Builder<MyApp>()
}
The Application class
class MyApp : DaggerApplication() {
override fun applicationInjector(): AndroidInjector<MyApp> =
DaggerAppComponent.builder().create(this@MyApp)
}
The BroadcastReceiver class
class MyTestReceiver : BroadcastReceiver() {
@Inject
lateinit var anInjectedObject: MyInjectObject
override fun onReceive(context: Context, intent: Intent) {
AndroidInjection.inject(this, context)
anInjectedObject.doSomthing()
}
}
It might be too late to answer this question, but I will provide an example from my recent project where I tried to inject AppWidgetProvider
which is a direct subclass of BroadcastReceiver
.
We need to inject a retrofit service into a BroadcastReceiver
:
@Module
public class NetModule {
/** shrunk for simplicity's sake. **/
@Singleton
@Provides
public WidgetService provideWidgetService(Application application, OkHttpClient client, Gson gson) {
return new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.baseUrl(application.getString(R.string.api_url))
.client(client)
.build()
.create(WidgetService.class);
}
}
Create another abstract @Module
for the with abstract methods annotated with @ContributesAndroidInjector
that return BroadcastReceiver
s you want to inject:
/**
* To inject the app widgets.
*/
@Module
public abstract class WidgetsModule {
@ContributesAndroidInjector
abstract IngredientsWidget contributesIngredientsWidget();
}
If you forgot to add this module, you will get error like:
java.lang.IllegalArgumentException: No injector factory bound for Class<>
Then the component with both modules, besides AndroidInjectionModule
@Singleton
@Component(modules = {AndroidInjectionModule.class, NetModule.class, WidgetsModule.class})
public interface AppComponent {
void inject(RecipesApp recipesApp);
}
Then in your Application
class you implement HasBroadcastReceiverInjector
interface.
public class RecipesApp extends Application implements HasBroadcastReceiverInjector {
@Inject
DispatchingAndroidInjector<BroadcastReceiver> broadcastReceiverInjector;
@Override
public void onCreate() {
super.onCreate();
component().inject(this);
}
public AppComponent component() {
return DaggerAppComponent.builder()
.build();
}
@Override
public AndroidInjector<BroadcastReceiver> broadcastReceiverInjector() {
return broadcastReceiverInjector;
}
}
Finally, you can inject your BroadcastReceiver inside onReceive() before calling the super().
public class IngredientsWidget extends AppWidgetProvider {
@Inject
public WidgetService api;
@Override
public void onReceive(Context context, Intent intent) {
/** Don't forget this line **/
AndroidInjection.inject(this, context);
super.onReceive(context, intent);
}
}
You can find more about how to inject android components docs.
I built a small sample: broadcast-injection.