android.support.v4.app.FragmentManager cannot be provided without an @Provides- or @Produces-annotated method

error: [dagger/missingbinding] cannot be provided without an @provides-annotated method.
android.content.context cannot be provided without an @provides-annotated method.
accountrepository cannot be provided without an provides annotated method
retrofit2 retrofit cannot be provided without an @provides-annotated method
dagger-android
dagger 2
a binding with matching key exists in component
no injector factory bound for class activity

So i'm quite new to Dagger and trying to "daggerify" Kotlin MVP project with activities plus independent fragments plus independent navigation.

The fact that i'm using a good few views based on support lib's Fragment made me try recent dagger android support features. After some struggling with compononent graph building i've faced the issue which is represented by this error:

e: ...\MyApp\app\build\tmp\kapt3\stubs\debug\com\...\di\app\MyAppComponent.java:6: error: [dagger.android.AndroidInjector.inject(T)] android.support.v4.app.FragmentManager cannot be provided without an @Provides- or @Produces-annotated method.
e: 
e: public abstract interface MyAppComponent extends dagger.android.AndroidInjector<myapp.ui.MyApp> {
e:                 ^
e:       android.support.v4.app.FragmentManager is injected at
e:           myapp.ui.common.BaseActivity.fragmentManager
e:       myapp.ui.main.MainActivity is injected at
e:           dagger.android.AndroidInjector.inject(arg0)
e: java.lang.IllegalStateException: failed to analyze: org.jetbrains.kotlin.kapt3.diagnostic.KaptError: Error while annotation processing
    at org.jetbrains.kotlin.analyzer.AnalysisResult.throwIfError(AnalysisResult.kt:57)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules(KotlinToJVMBytecodeCompiler.kt:137)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:158)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:61)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:107)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:51)
    at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:92)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$1$2.invoke(CompileServiceImpl.kt:386)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$1$2.invoke(CompileServiceImpl.kt:96)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:892)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:96)
    at org.jetbrains.kotlin.daemon.common.DummyProfiler.withMeasure(PerfUtils.kt:137)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl.checkedCompile(CompileServiceImpl.kt:919)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl.doCompile(CompileServiceImpl.kt:891)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:385)
    at sun.reflect.GeneratedMethodAccessor95.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:346)
    at sun.rmi.transport.Transport$1.run(Transport.java:200)
    at sun.rmi.transport.Transport$1.run(Transport.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.jetbrains.kotlin.kapt3.diagnostic.KaptError: Error while annotation processing
    at org.jetbrains.kotlin.kapt3.AnnotationProcessingKt.doAnnotationProcessing(annotationProcessing.kt:90)
    at org.jetbrains.kotlin.kapt3.AnnotationProcessingKt.doAnnotationProcessing$default(annotationProcessing.kt:42)
    at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.runAnnotationProcessing(Kapt3Extension.kt:205)
    at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:166)
    at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:82)
    at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM$analyzeFilesWithJavaIntegration$2.invoke(TopDownAnalyzerFacadeForJVM.kt:96)
    at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:106)
    at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:83)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:376)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:67)
    at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:96)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:367)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules(KotlinToJVMBytecodeCompiler.kt:132)
    ... 29 more

FAILED
FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:kaptDebugKotlin'.

Here is some code.

App:

class MyApp : MultiDexApplication(), HasActivityInjector {

    @Inject
    @JvmField
    var activityInjector: DispatchingAndroidInjector<Activity>? = null

    override fun onCreate() {
        super.onCreate()
        DaggerMyAppComponent.builder().create(this).inject(this)
    }

    override fun activityInjector(): AndroidInjector<Activity>? {
        return activityInjector
    }
}

AppComponent:

@Singleton
@Component(modules = [
    MyAppModule::class,
    DataModule::class,
    PreferencesModule::class,
    ServiceModule::class
])
interface MyAppComponent : AndroidInjector<MyApp> {

    @Component.Builder
    abstract class Builder : AndroidInjector.Builder<MyApp>()
}

AppModule:

@Module(includes = [AndroidSupportInjectionModule::class])
abstract class MyAppModule {

    @Binds
    @Singleton
    abstract fun application(myApp: MyApp): Application

    @PerActivity
    @ContributesAndroidInjector(modules = [(MainActivityModule::class)])
    abstract fun mainActivityInjector(): MainActivity

    //... other activity injectors
}

BaseActivityModule:

@Module
abstract class BaseActivityModule {

    @Binds
    @PerActivity
    internal abstract fun activity(appCompatActivity: AppCompatActivity): Activity

    @Binds
    @PerActivity
    internal abstract fun activityContext(activity: Activity): Context

    @Module
    companion object {

        const val ACTIVITY_FRAGMENT_MANAGER = "BaseActivityModule.activityFragmentManager"

        @JvmStatic
        @Provides
        @Named(ACTIVITY_FRAGMENT_MANAGER)
        @PerActivity
        fun activityFragmentManager(activity: AppCompatActivity): FragmentManager {
            return activity.supportFragmentManager
        }
    }
}

BaseFragmentModule:

@Module
class BaseFragmentModule {

    @Module
    companion object {

        const val FRAGMENT = "BaseFragmentModule.fragment"
        const val CHILD_FRAGMENT_MANAGER = "BaseFragmentModule.childFragmentManager"

        @JvmStatic
        @Provides
        @Named(CHILD_FRAGMENT_MANAGER)
        @PerFragment
        fun childFragmentManager(@Named(FRAGMENT) fragment: Fragment): FragmentManager {
            return fragment.childFragmentManager
        }
    }
}

BaseChildFragmentModule:

@Module
class BaseChildFragmentModule {
    companion object {
        const val CHILD_FRAGMENT = "BaseChildFragmentModule.childFragment"
    }
}

Sample MainActivityModule:

@Module(includes = [
    BaseActivityModule::class
])
abstract class MainActivityModule {

    @Binds
    @PerActivity
    abstract fun appCompatActivity(mainActivity: MainActivity): AppCompatActivity

    @PerFragment
    @ContributesAndroidInjector(modules = [LocationFragmentModule::class])
    abstract fun locationFragmentInjector(): LocationFragment

    //... other related fragments injection methods
}

I treat fragments as independent views, so each fragment has 1 View Module and 1 Presenter Module ATM. Here is the sample of fragment's DI parts:

@Module(includes = [BaseFragmentModule::class, LocationPresenterModule::class])
abstract class LocationFragmentModule {

    @Binds
    @Named(BaseFragmentModule.FRAGMENT)
    @PerFragment
    abstract fun fragment(locationFragment: LocationFragment): Fragment

    @Binds
    @PerFragment
    abstract fun locationView(locationFragment: LocationFragment): LocationView
}

@Module
abstract class LocationPresenterModule {

    @Binds
    @PerFragment
    abstract fun locationPresenter(locationPresenterImpl: LocationPresenterImpl): LocationPresenter
}

Gradle dagger dependencies:

implementation "com.google.dagger:dagger:$dagger_version"
kapt  "com.google.dagger:dagger-compiler:$dagger_version"
implementation "com.google.dagger:dagger-android:$dagger_version"
kapt  "com.google.dagger:dagger-android-processor:$dagger_version"
implementation "com.google.dagger:dagger-android-support:$dagger_version"
kapt  "com.google.dagger:dagger-android-support:$dagger_version"

I've tried to move AndroidSupportInjectionModule::class one level higher, to main component's modules array.

I hope it's framework-related code generation issue and I just have a bad understanding of support mechanism behaviour, because all module's parts where @Provides is supposed to be already contain this annotation.

As it can be seen from MyApp class code snippet, currently i'm stuck to extend MultiDexApplication, so i wonder could this issue be related to MultiDex supporting.

The situation looks strange to me, so I'd like to be pointed in the right direction by more experienced dagger users.

EDIT:

Here is BaseActivity code:

abstract class BaseActivity : AppCompatActivity(), HasSupportFragmentInjector {

    @Inject
    @JvmField
    var navigationManager: NavigationManager? = null

    @Inject
    @JvmField
    var locationManager: MyLocationManagerImpl? = null

    @Inject
    @JvmField
    @Named(BaseActivityModule.ACTIVITY_FRAGMENT_MANAGER)
    //Tried to replace with option below
    //@field:Named(BaseActivityModule.ACTIVITY_FRAGMENT_MANAGER)
    var fragmentManager: FragmentManager? = null

    @Inject
    @JvmField
    var fragmentInjector: DispatchingAndroidInjector<Fragment>? = null

    override fun onCreate(@Nullable savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
    }

    override fun supportFragmentInjector(): AndroidInjector<Fragment>? {
        return fragmentInjector
    }
}

BaseFragment:

abstract class BaseFragment : Fragment(), HasSupportFragmentInjector {

    @Inject
    @JvmField
    var activityContext: Context? = null

    @Inject
    @JvmField
    var parentActivity: FragmentActivity? = null

    @Inject
    @JvmField
    var fragmentListener: FragmentListener? = null

    @Inject
    @JvmField
    @Named(BaseFragmentModule.CHILD_FRAGMENT_MANAGER) 
    //Also tried option below
    //@field:Named(BaseFragmentModule.CHILD_FRAGMENT_MANAGER)
    var ownChildFragmentManager: FragmentManager? = null

    @Inject
    @JvmField
    var childFragmentInjector: DispatchingAndroidInjector<Fragment>? = null

    override fun onAttach(context: Context) {
        AndroidSupportInjection.inject(this)
        if (context is FragmentListener) {
            parentActivity = context as FragmentActivity
            fragmentListener = context
        }
        super.onAttach(context)
    }

    @Suppress("DEPRECATION")
    override fun onAttach(activity: Activity) {
        AndroidSupportInjection.inject(this)
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            if(activity is FragmentListener) {
                parentActivity = activity as FragmentActivity
                fragmentListener = activity
            }
        }
        super.onAttach(activity)
    }

    override fun supportFragmentInjector(): AndroidInjector<Fragment>? {
        return childFragmentInjector
    }

    fun addChildFragment(@IdRes containerViewId: Int, fragment: Fragment) {
        childFragmentManager!!.beginTransaction()
                .add(containerViewId, fragment)
                .commit()
    }
}

Also, full error code was added to the top.

Please try @Inject @field:Named instead @Inject @Named in every case where you use named annotation. It's helped me.

@ContributesAndroidInjector: Cannot be provided without an , "@ContributesAndroidInjector" could not inject the fragment view interface @​ContributesAndroidInjector: Cannot be provided without an @Provides-​annotated method. https://github.com/jega-ms/android-dagger2-mvp-rx/blob/​master/app/src/ 2020 GitHub, Inc. Terms · Privacy · Security · Status · Help. @devtechvalens Please check if all the dependencies are satisfied for the LoginPresenter.. Also check that the interface LoginMvpPresenter is provided by a @Provides method by casting the LoginPresenter.

Ok, in this separate case the reason was in non-proper assignments of Fragment objects in activity and operating them as own properties - more specifically, inside MainActivity, which extend the base class with filed injection of topical type.

So yes, dagger error log gave indirect hint where to dig.

Dagger-android application build failed · Issue #783 · google/dagger , Fragment>>> cannot be provided without an @Provides-annotated method. java.​util.Map<java.lang.Class<? extends android.support.v4.app. The problem: I can't provide Lazy<T> like this: @Provides public Lazy<DrawerLayout> provideDrawer Error:(17, 10) error: android.support.v4.widget.DrawerLayout cannot be provided without an @Inject constructor or from an @Provides- or @Pr

It looks like you are missing AndroidInjectionModule (or AndroidSupportInjectionModule if you use support fragments) installed on you AppComponent.

It should be like:

@Component(modules = {AndroidInjectionModule.class, MainAppModule.class}

Error:(16, 10) error: android.app.fragmentmanager cannot be , Error:(16, 10) error: android.app.fragmentmanager cannot be provided without an @provides- or @produces-annotated method  error: kotlin.jvm.functions.Function2<? super java.lang.Integer,? super java.lang.Integer,java.lang.Integer> cannot be provided without an @Provides- or @Produces-annotated method. Theoretically you could provide a kotlin.jvm.functions.Function2 but I failed to make it work. Even with this

How to get component dependencies in Dagger 2 - android, I have a Dagger2 Component for Fragment on Android. I initialize Dagger 2 error: dependency “cannot be provided without an #Inject constructor” MainActivity cannot be provided without an #Inject constructor or from an #​Provides- or #Produces-annotated method. getNavigationManager()] android.​support.v4.app. Error:(16, 10) error: android.app.fragmentmanager cannot be provided without an @provides- or @produces-annotated method Rate this: Please Sign up or sign in to vote.

[Dagger2] Cannot be provided without an @Provides-annotated , Error: [dagger.android.AndroidInjector.inject(T)] android.support.v4.app.​FragmentManager cannot be provided without an @Provides- or @Produces-​annotated method. Error:A binding with matching key exists in component:  android.support.v4.app.FragmentManager не может быть предоставлен без @ Provides- или @ Produces-аннотированного метода

Using Dagger in your Android app - Kotlin - Codelabs, r/CodingHelp: Create coding challenges, share your code, ask for help to fix your code. [Dagger2] Cannot be provided without an @Provides-annotated method. I am using FactoryPatter for ViewModel and when I do @Inject viewModel to fragment this error occures. I'm using android studio 4 with an androidx project. Answer 1 You can inject only the things that are provided in the classes annotated with @Module (only methods inside that module which are annotated with @Provides). So, you can do @Inject MainActivityPresenter presenter, for instance, not try to inject the whole module, like you tried to do.

Comments
  • I would guess that you try to @Inject fm : FragmentManager and not @Inject @Named(ACTIVITY_FRAGMENT_MANAGER) fm : FragmentManager? This could explain your issue. Please include the full error message and the relevant code, e.g. see here: stackoverflow.com/q/44912080/1837367
  • @DavidMedenjak, thanks for reply! I edited the question. So i tried to remove @Named(...) from all the relevant code, but nothing changes for now :( Anyway, thanks for the link - mb i'll find smth interesting in it.
  • @DavidMedenjak, actually I've tried to place @Named as well as remove it all across the code :) Just missed the clue while reading reply for the first time.
  • Was it the same error after adding the named annotation? I could imagine that you have a similar error in your BaseFragment. Adding @Named should resolve your issue. Please check your errors thoroughly
  • Well, stack trace hasn't changed after adding/removing @Named or @field:Named on desired fields. Hence I wonder: could the @Provides provider module's methods be the cause? Should I try other @Qualifier or smth instead? Here i have to say that i tried to completely remove @Named from module's providers too, but nothing changes. The other thought is: could the reason be in grabbing base classes (BaseActivitiy in my case), injected fields and use them as properties in extending activities, eg fragmentManager?.putFragment() or fragmentManager!!.putFragment()?