Android Library, Kotlin and Dagger2 - android

I'm building an application that have two modules: the Core module, that is an Android Library (com.android.library) and the Application module (com.android.application).
After I converted the Java files to Kotlin, the project is not compiling, giving me an error that the generated Dagger 2 files were not found (unresolved reference). But those files currently being generated under:
...core\build\generated\source\kapt\release{my\core\namespace}\DaggerBaseComponent.java
What I'm missing?
build.gradle (Core module)
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
...
android {
...
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
}
dependencies {
...
// Dagger.
kapt "com.google.dagger:dagger-compiler:2.10"
compile 'com.google.dagger:dagger:2.10'
provided 'javax.annotation:jsr250-api:1.0'
// Kotlin
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
build.gradle (Application module)
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
...
android {
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
}
dependencies {
...
// Dagger.
kapt "com.google.dagger:dagger-compiler:2.10"
compile 'com.google.dagger:dagger:2.10'
provided 'javax.annotation:jsr250-api:1.0'
// Kotlin
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
build.gradle (Project)
buildscript {
ext.kotlin_version = '1.1.2-3'
...
dependencies {
classpath 'com.android.tools.build:gradle:2.3.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
ApplicationContext.kt (of my Core Module)
class ApplicationContext : Application() {
var baseComponent: BaseComponent? = null
private set
override fun onCreate() {
super.onCreate()
initializeInjector()
}
private fun initializeInjector() {
// DaggerBaseComponent is and unresolved reference
baseComponent = DaggerBaseComponent.builder()
.appModule(AppModule(this))
.endpointModule(EndpointModule())
.build()
}
companion object {
operator fun get(context: Context): ApplicationContext {
return context.applicationContext as ApplicationContext
}
}
}

The problem was that Gradle was not finding the Dagger generated files by kapt, so I solved the problem by adding src/main/kapt to my sourceSets configuration on my Core module (lib):
build.gradle (Core module)
android {
...
sourceSets {
main.java.srcDirs += ['src/main/kotlin', 'src/main/kapt']
}
}
After that, the Core module started finding their Dagger 2 generated files.

Java module should have
plugins {
id("java-library")
id("kotlin")
id("kotlin-kapt")
}
java {
sourceSets {
main.java.srcDirs += ['build/generated/source/kapt/main']
}
}

Related

implementing hilt in android with kapt Execution failed for task ':app:kaptDebugKotlin'

I have been using hilt in my several android projects. But since I have updated my android studio to latest version Chipmunk// 2021.2.1, this error comes every time when I just build project
Execution failed for task ':app:kaptDebugKotlin'.
A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptWithoutKotlincTask$KaptExecutionWorkAction
java.lang.reflect.InvocationTargetException (no error message)
I am checking it on sample app which is just just one dependency injection, using hilt and kapt.
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
allprojects {
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
}
}
dependencies {
// Hilt Classpath for Java
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.38.1'
}
}
plugins {
id 'com.android.application' version '7.2.1' apply false
id 'com.android.library' version '7.2.1' apply false
id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
}
task clean(type: Delete) {
delete rootProject.buildDir
}
apply plugin: 'com.android.application'
apply plugin: 'org.jetbrains.kotlin.android'
apply plugin: 'kotlin-kapt'
apply plugin: 'dagger.hilt.android.plugin'
android {
compileSdk 32
defaultConfig {
applicationId "com.example.hiltkotlinpractice"
minSdk 21
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled 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'
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation("com.google.dagger:hilt-android:2.38.1")
kapt("com.google.dagger:hilt-android-compiler:2.38.1")
kapt 'androidx.hilt:hilt-compiler:1.0.0'
}
#HiltAndroidApp
class App: Application()
#Module
#InstallIn(ActivityComponent::class)
class AppModule {
#Provides
fun provideInterface(): APIProvider {
return APIProvider()
}
}
class Repo #Inject constructor(
val apiProvider: APIProvider
) {
fun get() = apiProvider.getData()
}
#AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private val TAG = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val repo = Repo(APIProvider())
Log.d(TAG, repo.get())
}
}
Try using "annotationProcessor" instead of the "kapt" in the build.gradle dependencies. Worked for me.

Dagger2 - FragmentSubcomponentBuilder does not implement AndroidInjector.Factory

I'm using dagger 2 and trying to translate my Android project from Java to Kotlin. After successful build i'm getting runtime error:
MyFragmentSubcomponentBuilder does not implement AndroidInjector.Factory
With Java this error not appeared. And also i noticed that in my module ActivityBuilder all methods are unused after build (they must be used in generated subcomponents classes).
#Module
abstract class ActivityBuilder {
// ...
#ContributesAndroidInjector(modules = arrayOf(MainActivityModule::class,MyFragmentProvider::class))
internal abstract fun bindMainActivity(): MainActivity // this method highlighted with gray color in AndroidStudio as unused
}
How can i setup my project to use dagger 2 and kotlin correctly ?
my top level gradle.build:
buildscript {
ext.kotlin_version = '1.1.51'
repositories {
jcenter()
maven { url 'https://maven.google.com' }
mavenCentral()
google()
maven {
url 'https://github.com/uPhyca/stetho-realm/raw/master/maven-repo'
}
maven {
url "https://jitpack.io"
}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0'
classpath 'com.google.gms:google-services:3.1.0'
classpath "io.realm:realm-gradle-plugin:3.0.0"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
// ...
And app build.gradle:
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'realm-android'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
applicationId "com.example.app"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0.0"
multiDexEnabled true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
dataBinding {
enabled = true
}
kapt {
generateStubs = true
}
}
// ...
kapt {
generateStubs = true
}
dependencies {
// ...
kapt 'com.android.databinding:compiler:3.0.0'
//Dagger 2 dependencies
compile 'com.google.dagger:dagger:2.11'
compile 'com.google.dagger:dagger-android:2.11'
compile 'com.google.dagger:dagger-android-support:2.11'
kapt 'com.google.dagger:dagger-compiler:2.11'
kapt 'com.google.dagger:dagger-android-processor:2.11'
// ...
}
As you can see i not using annotationProcessor for dagger 2 (only kapt), and also i added generateStubs = true. But i still getting error in runtime.
Put AndroidSupportInjectionModule in your array module in ApplicationComponent
For example
#Singleton
#Component(
modules = arrayOf(
AndroidSupportInjectionModule::class,
ActivityBuilder::class,
AppModule::class
)
)
interface AppComponent : AndroidInjector<App> {
#Component.Builder
abstract class Builder : AndroidInjector.Builder<App>()
}

Testing environment configuration: Android + JUnit 5 + Mockito + Spek + Kotlin

I'm having hard time with configuration of a testing environment based on JUnit Jupiter (5). I have two different errors there:
WARNING: TestEngine with ID 'spek' failed to discover tests
org.junit.platform.commons.util.PreconditionViolationException: Could not load class with name...
Exception in thread "main" java.lang.NoSuchMethodError: org.junit.platform.launcher.Launcher.execute(Lorg/junit/platform/launcher/LauncherDiscoveryRequest;)V
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:61)...
And the configuration goes as follows.
Main build.gradle:
apply plugin: 'org.junit.platform.gradle.plugin'
buildscript {
ext.kotlin_version = '1.1.4-3'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0-beta5'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.junit.platform:junit-platform-gradle-plugin:1.0.0"
classpath "de.mannodermaus.gradle.plugins:android-junit5:1.0.0"
}
}
allprojects {
repositories {
google()
jcenter()
maven { url "http://dl.bintray.com/jetbrains/spek" }
}
}
junitPlatform {
filters {
engines {
include 'spek'
}
}
}
Module build.gradle:
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'de.mannodermaus.android-junit5'
android {
compileSdkVersion 26
buildToolsVersion "26.0.0"
defaultConfig {
...
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
...
compileOptions {
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'com.android.support:appcompat-v7:26.0.2'
implementation 'com.android.support:recyclerview-v7:26.0.2'
testImplementation 'org.jetbrains.spek:spek-api:1.1.4'
testImplementation 'org.jetbrains.spek:spek-junit-platform-engine:1.1.4'
testImplementation junit5()
// testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.0.0' not needed when using the one above
testImplementation 'org.junit.platform:junit-platform-runner:1.0.0'
testImplementation 'org.mockito:mockito-core:2.8.47'
testImplementation 'com.nhaarman:mockito-kotlin-kt1.1:1.5.0'
testCompileOnly "de.mannodermaus.gradle.plugins:android-junit5-embedded-runtime:1.0.0"
}
This configuration is supposed to be based on https://github.com/aurae/android-junit5. But I also tried without it.
Have anyone managed to find a working configuration of dependencies for these libraries?
As posted here https://stackoverflow.com/a/48427771/4249825 you need the following in your build.gradle:
app's build.grale:
buildscript {
...
dependencies {
...
classpath "de.mannodermaus.gradle.plugins:android-junit5:1.0.30" // latest atm
}
}
module's build.gradle:
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: "de.mannodermaus.android-junit5"
android {
...
sourceSets {
test.java.srcDirs += 'src/test/kotlin'
androidTest.java.srcDirs += 'src/androidTest/kotlin'
}
}
project.ext {
spekVersion = "1.1.5" // latest atm
mockitoKotlinVersion = "2.0.0-alpha02" // latest atm
kluentVersion = "1.34" // latest atm
}
dependencies {
...
//
// TESTS
testCompile "com.nhaarman.mockitokotlin2:mockito-kotlin:$mockitoKotlinVersion"
testImplementation "org.amshove.kluent:kluent-android:$kluentVersion"
testImplementation("org.jetbrains.spek:spek-api:$spekVersion") {
exclude group: "org.jetbrains.kotlin"
}
testImplementation("org.jetbrains.spek:spek-junit-platform-engine:$spekVersion") {
exclude group: "org.junit.platform"
exclude group: "org.jetbrains.kotlin"
}
testImplementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
testImplementation junit5.unitTests()
// see https://github.com/mannodermaus/android-junit5#android-studio-workarounds
testCompileOnly junit5.unitTestsRuntime()
}

Could not find class databinding.FragmentBinding

I'm trying to use databinding in my fragment but I get the following error on runtime:
Could not find class 'com.example.databinding.FragmentUpSellBinding', referenced from method com.example.UpSellFragment.onCreateView
Which results into:
FATAL EXCEPTION: main Process: nl.anwb.fietsen.debug, PID: 5563
java.lang.IllegalStateException: DataBindingUtil.inflate(…r,
false) must not be null`
my build.gradle looks like this:
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
android {
dataBinding {
enabled = true
}
}
kapt {
generateStubs = true
}
dependencies {
kapt 'com.android.databinding:compiler:3.0.0-alpha4'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
}
Main buid.gradle
buildscript {
ext.kotlin_version = '1.1.2-4'
ext{
supportLibraryVersion = '25.3.1'
}
repositories {
maven { url 'https://maven.google.com' }
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0-alpha4'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
Does anyone know how I can fix this?
build.gradle in you don't need
dataBinding {
enabled = true
}
Remove and try
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
kapt {
generateStubs = true
}
dependencies {
kapt 'com.android.databinding:compiler:3.0.0-alpha4'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
}
And update your Kotlin to
ext.kotlin_version = '1.1.3-2'
Sanne, I have the exact same build.gradle files as you, except for a newer gradle -alpha9 and don't get the runtime error from onCreateView when using DataBindingUtil.inflate(inflater,...).
In my case dataBinding { enabled = true } is required.
However I did get a build error (Unresolved reference: databinding) when using FragmentXBinding.inflate(inflater) until I specified FragmentXBinding.inflate(inflater as LayoutInflater).

Intellij Idea 2016.3 complains about Android API level in non-Android module

My project is build by gradle and is structured into android, core, desktop modules. Where android is an Android module, but both core and desktop modules are java modules. The core is dependency of both android and desktop. When I write (in desktop):
Queue<P> qeueue= new ArrayDeque<P>();
The Idea complains:
Cast from ArrayDeque to Queue requires API level 9 (current min is 1)
How can I avoid this complain? Disable the inspection on whole project doesn't seems right. I also do not want to convert the desktop to be an Android module.
Project's build.gradle:
buildscript {
repositories {
// repositories
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.3'
}
}
allprojects {
apply plugin: "idea"
version = '1.0'
ext {
appName = 'my-app-name'
}
repositories {
// repositories
}
}
project(":desktop") {
apply plugin: "java"
dependencies {
compile project(":core")
// some dependencies here
}
}
project(":android") {
apply plugin: "android"
configurations { natives }
dependencies {
compile project(":core")
// some other dependencies here
}
}
project(":core") {
apply plugin: "java"
dependencies {
// some dependencies here
}
}
Core's build.gradle:
apply plugin: "java"
sourceCompatibility = 1.6
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
sourceSets.main.java.srcDirs = ["src/", "postprocessing/", "gl/", "math/", "experiment/"]
dependencies {
}
Desktop's build.gradle:
apply plugin: "java"
sourceCompatibility = 1.8
sourceSets.main.java.srcDirs = ["src/", "experiment/", "resources/"]
project.ext.mainClassName = "cz.plajt.wallp.hills.desktop.DesktopLauncher"
project.ext.assetsDir = new File("../android/assets");
task run(dependsOn: classes, type: JavaExec) {
main = project.mainClassName
classpath = sourceSets.main.runtimeClasspath
standardInput = System.in
workingDir = project.assetsDir
ignoreExitValue = true
}
task dist(type: Jar) {
from files(sourceSets.main.output.classesDir)
from files(sourceSets.main.output.resourcesDir)
from { configurations.compile.collect { zipTree(it) } }
from files(project.assetsDir);
manifest {
attributes 'Main-Class': project.mainClassName
}
}
dist.dependsOn classes
dependencies {
}
This is a known issue for IntelliJ, and I am facing the same issue. I can't even get the project to compile in IntelliJ.
https://youtrack.jetbrains.com/issue/IDEA-122904
There doesn't seem to be a workaround for this.

Categories

Resources