First of all, and just in case, I've read plenty of posts (like this) with no luck so don't mark this as duplicate please.
I'm new to Hilt, and trying to implement it in my multi-module app, but for the moment cannot even get my app to start.
I have a class called AppSettings in a module called "Common" -which is accesible from all modules- which holds (as the name says) all app configuration.
I'm following the Hilt documentation and the first I've done is to add dependencies (done it in all project modules).
Project build.gradle:
buildscript {
ext.kotlin_version = '1.7.10'
repositories {
jcenter()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.2.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath("com.google.dagger:hilt-android-gradle-plugin:2.38.1")
}
ext.java_version = JavaVersion.VERSION_1_8
}
allprojects {
repositories {
jcenter()
mavenCentral()
maven { url "https://jitpack.io" }
maven { url 'https://repository-achartengine.forge.cloudbees.com/snapshot/' }
maven { url 'def androidHome = System.getenv("ANDROID_HOME")' }
maven { url "/Home/MrDeveloper/Android/Sdk/extras/android/m2repository/" }
google()
}
}
app build.gradle:
plugins {
id 'dagger.hilt.android.plugin'
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
}
android {
compileSdkVersion 32
def code
Properties versionProps = new Properties()
def versionPropsFile = file('version.properties')
if (versionPropsFile.exists())
versionProps.load(new FileInputStream(versionPropsFile))
code = (versionProps['VERSION_CODE'] ?: "0").toInteger() + 1
versionProps['VERSION_CODE'] = code.toString()
versionProps.store(versionPropsFile.newWriter(), null)
packagingOptions {
resources {
pickFirsts += ['META-INF/LICENSE.txt']
excludes += ['META-INF/NOTICE.md', 'META-INF/LICENSE.md', 'META-INF/INDEX.LIST', 'META-INF/DEPENDENCIES', 'META-INF/io.netty.versions.properties']
}
}
defaultConfig {
minSdkVersion 23
targetSdkVersion 32
versionCode code
versionName "2.0." + code
// next ndk abifilters have to be disabled if spli apk is enabled.
// ndk.abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'//testing
multiDexEnabled true
compileOptions {
sourceCompatibility java_version
targetCompatibility java_version
}
}
compileOptions {
sourceCompatibility java_version
targetCompatibility java_version
}
splits {
// Configures multiple APKs based on ABI.
abi {
// Enables building multiple APKs per ABI.
enable true
// By default all ABIs are included, so use reset() and include to specify that we only
// want APKs for x86 and x86_64.
// Resets the list of ABIs that Gradle should create APKs for to none.
reset()
// Specifies a list of ABIs that Gradle should create APKs for.
include "armeabi-v7a"
include "arm64-v8a"
include "x86"
include "x86_64"
}
}
buildTypes {
release {
/*signingConfig signingConfigs.release*/
minifyEnabled false
shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
// This next piece of code is used by apk Split
applicationVariants.all { variant ->
variant.outputs.all { output ->
project.ext { appName = 'artandwords' }
def newName = 'artandwords_' + output.getFilter(com.android.build.OutputFile.ABI) + '.apk'
outputFileName = new File("./", newName)
}
// assign different version code for each output
variant.outputs.each { output ->
output.versionCodeOverride =
//project.ext.versionCodes.get(output.getFilter(OutputFile.ABI)) * 1000 + android.defaultConfig.versionCode
project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI)) * 1000 + code - 1000
}
}
}
debug {
}
}
allprojects {
repositories {
jcenter()
mavenCentral()
def androidHome = System.getenv("ANDROID_HOME")
maven {
url "$androidHome/extras/android/m2repository/"
}
maven {
url "https://maven.java.net/content/groups/public/"
}
}
}
productFlavors {
}
androidResources {
ignoreAssetsPattern '!*ffprobe'
}
lint {
abortOnError false
checkReleaseBuilds false
}
dataBinding{
enabled = true
}
}
// This next piece of code is used by apk Split
// map for the version code that gives each ABI a value. make sure to list all ABIs mentioned in splits block, an keep the order.
ext.versionCodes = ['armeabi-v7a': 1, 'arm64-v8a': 2, 'x86': 3, 'x86_64': 4]
dependencies {
//ffmpeg
implementation 'com.arthenica:mobile-ffmpeg-min-gpl:4.2.2.LTS'
//implementation 'com.arthenica:mobile-ffmpeg-full:4.3.1'
//Google Guava
api 'com.google.guava:guava:31.1-jre'
//volley
api 'com.android.volley:volley:1.2.1'
//spotify
api 'com.github.kaaes:spotify-web-api-android:0.4.1'
//apache commons lang
implementation group: 'org.apache.commons', name: 'commons-text', version: '1.9'
//Font Selector List Preference
api 'com.vanniktech:vntfontlistpreference:1.0.0'
//Rate my app
api 'com.github.hotchemi:android-rate:1.0.1'
//Support
api 'androidx.appcompat:appcompat:1.4.2'
api 'androidx.legacy:legacy-support-v4:1.0.0'
//AlertDialog
implementation 'com.github.d-max:spots-dialog:1.1@aar'
//glide animated gifs
implementation 'com.github.bumptech.glide:glide:4.13.2'
implementation 'androidx.viewpager2:viewpager2:1.0.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.13.2'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
//preference
implementation 'androidx.preference:preference-ktx:1.2.0'
//
api 'com.rockerhieu:rv-adapter-endless:1.2'
implementation 'com.squareup.picasso:picasso:2.71828'
//flat-dialog
implementation 'com.github.mejdi14:Flat-Dialog-Android:1.0.5'
//Hilt
implementation('com.google.dagger:hilt-android:2.42')
annotationProcessor('com.google.dagger:hilt-android-compiler:2.42')
//implementation 'com.google.dagger:hilt-android:2.42'
//implementation 'androidx.navigation:navigation-fragment-ktx:2.5.0'
//implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03'
//annotationProcessor 'androidx.hilt:hilt-compiler:1.0.0'
//annotationProcessor 'com.google.dagger:hilt-android-compiler:2.42'
implementation project(':Common')
implementation project(':DTO')
implementation project(':Core')
}
I've added the same Hilt dependencies in all project modules and everything builds fine.
Then, in my AppSettings activity I've added the required directive so I can then inject it anywhere I need it:
@HiltAndroidApp
class AppSettings : MultiDexApplication() {
val infoAlertBkgColor1 = "#60a69e"
...
override fun onCreate() {
super.onCreate()
}
}
In my MainActivity:
@AndroidEntryPoint
class MainActivity : FragmentActivity(), IActionListeners, IImageListeners,
OnListFragmentInteractionListener {
@Inject lateinit var app: AppSettings
...
whatever
}
And after launching the app:
2022-07-17 15:51:27.268 8574-8574/com.myapp.myapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.myapp.myapp, PID: 8574
java.lang.RuntimeException: Unable to instantiate application app.AppSettings: java.lang.ClassNotFoundException: Didn't find class "app.AppSettings" on path: DexPathList[[zip file "/data/app/~~umETXnca3-spQEy4jvBm2Q==/com.myapp.myapp-QfTlJr20Dw0ZWFvJSqfnvg==/base.apk"],nativeLibraryDirectories=[/data/app/~~umETXnca3-spQEy4jvBm2Q==/com.myapp.myapp-QfTlJr20Dw0ZWFvJSqfnvg==/lib/arm64, /data/app/~~umETXnca3-spQEy4jvBm2Q==/com.myapp.myapp-QfTlJr20Dw0ZWFvJSqfnvg==/base.apk!/lib/arm64-v8a, /system/lib64, /system_ext/lib64]]
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 "app.AppSettings" on path: DexPathList[[zip file "/data/app/~~umETXnca3-spQEy4jvBm2Q==/com.myapp.myapp-QfTlJr20Dw0ZWFvJSqfnvg==/base.apk"],nativeLibraryDirectories=[/data/app/~~umETXnca3-spQEy4jvBm2Q==/com.myapp.myapp-QfTlJr20Dw0ZWFvJSqfnvg==/lib/arm64, /data/app/~~umETXnca3-spQEy4jvBm2Q==/com.myapp.myapp-QfTlJr20Dw0ZWFvJSqfnvg==/base.apk!/lib/arm64-v8a, /system/lib64, /system_ext/lib64]]
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:52)
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: Lapp/Hilt_AppSettings;
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 "app.Hilt_AppSettings" on path: DexPathList[[zip file "/data/app/~~umETXnca3-spQEy4jvBm2Q==/com.myapp.myapp-QfTlJr20Dw0ZWFvJSqfnvg==/base.apk"],nativeLibraryDirectories=[/data/app/~~umETXnca3-spQEy4jvBm2Q==/com.myapp.myapp-QfTlJr20Dw0ZWFvJSqfnvg==/lib/arm64, /data/app/~~umETXnca3-spQEy4jvBm2Q==/com.myapp.myapp-QfTlJr20Dw0ZWFvJSqfnvg==/base.apk!/lib/arm64-v8a, /system/lib64, /system_ext/lib64]]
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
AndroidManifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"
android:anyDensity="true"
android:resizeable="true"/>
<application
android:name="app.AppSettings"
android:enabled="true"
android:allowBackup="true"
android:fullBackupContent="true"
android:hardwareAccelerated="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:largeHeap="true"
tools:replace="android:theme"
android:theme="@style/Theme.myTheme.TitleBar">
<uses-library
android:name="org.apache.http.legacy"
android:required="false" />
...activities...
<receiver android:name=".helpers.notification.receiver.AlarmReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.NOTIFY" />
</intent-filter>
</receiver>
<receiver android:name=".helpers.notification.receiver.BootReceiver"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<service
android:name=".helpers.notification.service.AlarmService"
android:enabled="true"/>
<service
android:name=".helpers.audio.PlayMp3Service"
android:enabled="true"/>
<provider
android:name=".helpers.GenericFileProvider"
android:authorities="${applicationId}.helpers.GenericFileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
</application>
</manifest>
Any help to get rid of this? (tried disabling Multidex with no luck, but anyway I need it)
Edit 1:
If I move the application class (the one using @HiltAndroidApp directive) to the application itself (and not in a module) the error changes, now it complains about MainActivity (the main activity using @AndroidEntryPoint directivity) not existing.