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 BroadcastReceivers 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.