Search code examples
androidandroid-jetpack-composedagger-hiltkapt

Cannot implement Hilt with Compose Activity


I am trying to implement dagger Hilt in an android app that uses Jetpack Compose. I have previously used Hilt but this is the first time with a compose project.

This is the error that I get when I try to run the app:

java.lang.RuntimeException: Unable to instantiate application com.juegosdemesa.saltaconejo.SaltaConejoApplication: java.lang.ClassNotFoundException: Didn't find class "com.juegosdemesa.saltaconejo.SaltaConejoApplication" on path: DexPathList[[dex file "/data/data/com.juegosdemesa.saltaconejo/code_cache/.overlay/base.apk/classes7.dex", zip file "/data/app/~~fvjcQ4ZxOw99F2GO-9kvnw==/com.juegosdemesa.saltaconejo-DffqHuQR9C6r5HE_rQmgJw==/base.apk"],nativeLibraryDirectories=[/data/app/~~fvjcQ4ZxOw99F2GO-9kvnw==/com.juegosdemesa.saltaconejo-DffqHuQR9C6r5HE_rQmgJw==/lib/x86, /system/lib, /system_ext/lib]]
at android.app.LoadedApk.makeApplication(LoadedApk.java:1244)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6683)
at android.app.ActivityThread.access$1300(ActivityThread.java:237)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1913)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.juegosdemesa.saltaconejo.SaltaConejoApplication" on path: DexPathList[[dex file "/data/data/com.juegosdemesa.saltaconejo/code_cache/.overlay/base.apk/classes7.dex", zip file "/data/app/~~fvjcQ4ZxOw99F2GO-9kvnw==/com.juegosdemesa.saltaconejo-DffqHuQR9C6r5HE_rQmgJw==/base.apk"],nativeLibraryDirectories=[/data/app/~~fvjcQ4ZxOw99F2GO-9kvnw==/com.juegosdemesa.saltaconejo-DffqHuQR9C6r5HE_rQmgJw==/lib/x86, /system/lib, /system_ext/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:207)
at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
at android.app.AppComponentFactory.instantiateApplication(AppComponentFactory.java:76)
at androidx.core.app.CoreComponentFactory.instantiateApplication(CoreComponentFactory.java:51)
at android.app.Instrumentation.newApplication(Instrumentation.java:1158)
at android.app.LoadedApk.makeApplication(LoadedApk.java:1236)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6683) 
at android.app.ActivityThread.access$1300(ActivityThread.java:237) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1913) 
at android.os.Handler.dispatchMessage(Handler.java:106) 
at android.os.Looper.loop(Looper.java:223) 
at android.app.ActivityThread.main(ActivityThread.java:7656) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 
Suppressed: java.lang.NoClassDefFoundError: Failed resolution of: Lcom/juegosdemesa/saltaconejo/Hilt_SaltaConejoApplication;
    at java.lang.VMClassLoader.findLoadedClass(Native Method)
    at java.lang.ClassLoader.findLoadedClass(ClassLoader.java:738)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:363)
    ... 14 more
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.juegosdemesa.saltaconejo.Hilt_SaltaConejoApplication" on path: DexPathList[[dex file "/data/data/com.juegosdemesa.saltaconejo/code_cache/.overlay/base.apk/classes7.dex", zip file "/data/app/~~fvjcQ4ZxOw99F2GO-9kvnw==/com.juegosdemesa.saltaconejo-DffqHuQR9C6r5HE_rQmgJw==/base.apk"],nativeLibraryDirectories=[/data/app/~~fvjcQ4ZxOw99F2GO-9kvnw==/com.juegosdemesa.saltaconejo-DffqHuQR9C6r5HE_rQmgJw==/lib/x86, /system/lib, /system_ext/lib]]
    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:207)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
    ... 17 more
[CIRCULAR REFERENCE:java.lang.NoClassDefFoundError: Failed resolution of: Lcom/juegosdemesa/saltaconejo/Hilt_SaltaConejoApplication;]

I understand that the application cannot find the MainActivity.

Here is the code of the activity:

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.ui.Modifier
import com.juegosdemesa.saltaconejo.ui.theme.SaltaConejoTheme
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            SaltaConejoTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    SaltaConejoApp()
                }
            }
        }
    }
}

Here is the AndroidManisfest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:name=".SaltaConejoApplication"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        tools:targetApi="31">

        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:theme="@style/Theme.SaltaConejo">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

The Application class:

@HiltAndroidApp
class SaltaConejoApplication: Application() {
    val applicationScope = CoroutineScope(SupervisorJob())

    /**
     * AppContainer instance used by the rest of classes to obtain dependencies
     */
    lateinit var container: AppContainer

    override fun onCreate() {
        super.onCreate()
        container = AppDataContainer(this)
    }
}

And this is the build.gradle:

plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
    //For Room substitute for kapt
    id("com.google.devtools.ksp")
    //For Hilt
    id("dagger.hilt.android.plugin")
    id("kotlin-kapt")
}

android {
    namespace = "com.juegosdemesa.saltaconejo"
    compileSdk = 34

    defaultConfig {
        applicationId = "com.juegosdemesa.saltaconejo"
        minSdk = 28
        targetSdk = 34
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables {
            useSupportLibrary = true
        }
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
    buildFeatures {
        compose = true
        viewBinding = true
    }
    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.1"
    }
    packaging {
        resources {
            excludes += "/META-INF/{AL2.0,LGPL2.1}"
        }
    }
}

dependencies {

    implementation("androidx.core:core-ktx:1.12.0")
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
    implementation("androidx.activity:activity-compose:1.8.2")
    implementation(platform("androidx.compose:compose-bom:2023.08.00"))
    implementation("androidx.compose.ui:ui")
    implementation("androidx.compose.ui:ui-graphics")
    implementation("androidx.compose.ui:ui-tooling-preview")
    implementation("androidx.compose.material3:material3")
    testImplementation("junit:junit:4.13.2")
    androidTestImplementation("androidx.test.ext:junit:1.1.5")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
    androidTestImplementation(platform("androidx.compose:compose-bom:2023.08.00"))
    androidTestImplementation("androidx.compose.ui:ui-test-junit4")
    debugImplementation("androidx.compose.ui:ui-tooling")
    debugImplementation("androidx.compose.ui:ui-test-manifest")

    //Library for tinder like card

    implementation ("com.github.AsynctaskCoffee:tinderlikecardstack:1.0")
    implementation ("com.google.android.material:material:1.11.0")
    implementation ("io.coil-kt:coil-compose:1.3.2")

    val navigationVersion = "2.7.6"
    implementation ("androidx.navigation:navigation-fragment-ktx:$navigationVersion")

    implementation ("com.alexstyl.swipeablecard:swipeablecard:0.1.0")
    implementation ("com.google.accompanist:accompanist-systemuicontroller:0.26.1-alpha")

    implementation ("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2")
    implementation ("androidx.compose.runtime:runtime-livedata:1.5.4")
    implementation ("androidx.navigation:navigation-compose:2.7.6")

    val roomVersion = "2.6.1"
    //Room
    implementation("androidx.room:room-runtime:$roomVersion")
    ksp("androidx.room:room-compiler:$roomVersion")
    implementation("androidx.room:room-ktx:$roomVersion")

    //Hilt
    val hiltVersion = 2.44
    implementation ("com.google.dagger:hilt-android:$hiltVersion")
    ksp ("com.google.dagger:hilt-android-compiler:$hiltVersion")
    implementation ("androidx.hilt:hilt-navigation-compose:1.1.0")
}

Top-level gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
    id("com.android.application") version "8.2.1" apply false
    id("org.jetbrains.kotlin.android") version "1.9.0" apply false
    id("com.google.devtools.ksp") version "1.9.0-1.0.13" apply false
    id("com.google.dagger.hilt.android") version "2.44" apply false
}

I used a previous working project as an example (no compose though) but still no good. Also I tried to used kapt for Hilt but in that case the app does not compile and all the feedback I get is java.lang.reflect.InvocationTargetException (no error message) which is not helpful at all

As a workaround I used this codelab as an example and the app compiles and works perfectly https://developer.android.com/codelabs/basic-android-kotlin-compose-persisting-data-room?hl=es-419#10

Any idea on what might happen?

Thank you in advanced


Solution

  • You need to do few modifications in dependencies:

    In build.gradle.kts - project level

    id("org.jetbrains.kotlin.android") version "1.9.10" apply false
    id("com.google.devtools.ksp") version "1.9.10-1.0.13" apply false
    id("com.google.dagger.hilt.android") version "2.47" apply false
    

    And in build.gradle.kts - app module

    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.3"
    }
    
    //Hilt
    val hiltVersion = 2.47
    implementation ("com.google.dagger:hilt-android:$hiltVersion")
    kapt ("com.google.dagger:hilt-android-compiler:$hiltVersion")
    implementation ("androidx.hilt:hilt-navigation-compose:1.0.0")