Search code examples
androiddagger-2aar

Exposing Dagger Components defined in an Android Library


How does an Android application in one gradle module include dagger @Modules defined in an other Android Library (.aar)?

I'm trying to have a generic library that provides a set of functionality defined thru dagger @Module's able to have have them injected into Applications that depend on that library

@Singleton
@Component(modules = {
        AndroidSupportInjectionModule.class,
        LibraryAppModule.class
})
public interface LibraryComponent extends AndroidInjector<DaggerApplication> {
    @Component.Builder
    interface Builder {
        @BindsInstance
        Builder application(Application application);
        LibraryComponent build();
    }

    void inject(LibraryApplication app);

    @Override
    void inject(DaggerApplication instance);
}
@Module
public class LibraryAppModule {

    @Provides
    @Singleton
    Context provideContext(Application application) {
        return application;
    }

    @Singleton
    @Provides
    ServiceFoo provideServiceFoo(Context context) {
        return new ServiceFoo(context);
    }

    @Singleton
    @Provides
    ServiceBar provideServiceBar(Context context, ServiceFoo serviceFoo) {
        return new ServiceBar(context, serviceFoo);
    }

}

Now in the Application that has a dependency for this library (build.gradle) I've tried the following:

implementation project(":Library")

Application using the library

@Singleton
@Component(modules = {
        AndroidSupportInjectionModule.class,
        LibraryAppModule.class
})
public interface ExampleApplicationComponent extends AndroidInjector<DaggerApplication> {

    @Component.Builder
    interface Builder {
        @BindsInstance
        Builder application(Application application);
        ExampleApplicationComponent build();
    }

    void inject(ExampleApplication app);

    @Override
    void inject(DaggerApplication instance);
}

The project layout - library and app depending on library This is an example of the place where I'm getting the issue (a null object). This is in a separate module that depends on the library.

public class MainActivity extends AppCompatActivity {

    @Inject
    ServiceFoo serviceFoo;

    @Inject
    ServiceBar serviceBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        serviceFoo.downloadImages();

        serviceBar.uploadImages();
    }
}

I expect to see the LibraryAppModule's services to be available in my Activities using @Inject. What am I doing wrong?


Solution

  • In order to resolve the issue 2 things needed to be done.

    1. The MainActivity had to extend DaggerAppCompatActivity (this ensures during onCreate() for our Activity that inject() is called, but for this to work there needs to be an AndroidInjector for the Activity.
    2. This is accomplished by using @ContributesAndroidInjector within a module that I defined and installed into the ExampleApplicationComponent
    @Module
    public abstract class ExampleApplicationActivityBuilder {
    
        @ContributesAndroidInjector
        abstract MainActivity bindMainActivity();
    }
    

    Now within the MainActivity, the Services I want injected from the library module are non-null.

    Here's is a git commit that shows the difference implementing this fix. https://github.com/PeregrineFalcon/DaggerExampleLibrary/commit/1ebfdecfa3684c7ac124b9f6a4cecd23712a74fd

    Hope this helps someone else who trying to do a multi-module Dagger Android project with @Modules provided through the library.