use @ContributesAndroidInjector based on (API level) condition

Viewed 132

I have a ServiceBinderModule in my Android app that is responsible for adding all my Services to the DI graph like this:

@ContributesAndroidInjector
@ServiceScope
internal abstract fun myAutofillService(): MyAutofillService

My problem is that I have a Service that extends android.service.autofill.AutofillService which is only available from Android O. On devices below that API level I have a different solution in place, but since I have MyAutofillService on the graph already, the app is crashing at startup (MyAutofillService already being in DaggerAppComponent but AutofillService not being present in the Android framework).

I saw this thread about this topic: https://github.com/google/dagger/issues/1064

It suggests to use dagger.android.experimentalUseStringKeys and @RequiresApi, but it has a warning: Keep in mind that enabling this also breaks incremental annotation processor support on Dagger 5.+, which I think is a dealbreaker. I'm also not comfortable putting experimental... stuff into a production app.

Any advice what I could do? I'd like to put MyAutofillService on the graph based on the device's API level.

1 Answers

If you don't want to use experimentalUseStringKeys, an option I like in that thread is to make a subcomponent for the higher API level. This subcomponent only needs to contain the MyAutofillService binding.

@RequiresApi(Build.VERSION_CODES.O)
@Subcomponent(modules = [MyApi26Module::class])
interface MyApi26Subcomponent : AndroidInjector<MyApplication>

@RequiresApi(Build.VERSION_CODES.O)
@Module
abstract class MyApi26Module {
    @ContributesAndroidInjector
    @ServiceScope
    internal abstract fun myAutofillService(): MyAutofillService
}

When you create your main component, you can check your SDK_INT to decide whether to install it directly or create MyApi26Subcomponent and install that instead.

Related