I am trying to share Java code between Android and JVM targets using Kotlin Multiplatform feature (sample project: https://github.com/dmitrykolesnikovich/accessJavaCode-issue)
Simply saying, ":library1" and ":library2" both are Kotlin multiplatform libraries targeting JVM and Android. ":library2" depends on ":library1". They both uses Kotlin and Java. ":library2" is intended to be dependency of 1) Android application and 2) desktop (JavaFX) application. That's why 1) AAR artifact and 2) JAR artifact both are needed (?) - so I use 1) Android target and 2) JVM target for both ":library1" and ":library2".
The problem is that, when I have Java code in ":library1"
public class JavaCode {} // JavaCode.java
And Kotlin code in ":library2" that depends on ":library1"
class AccessJavaCode : JavaCode() // AccessJavaCode.kt
Android target is OK with recognizing Java but JVM target is not:
> Task :library2:compileKotlinJvm FAILED
e: AccessJavaCode.kt: (3, 38): Unresolved reference: JavaCode
In gradle config I define two plugins: kotlin-multiplatform
and com.android.library
:
apply plugin: "kotlin-multiplatform"
apply plugin: "com.android.library"
kotlin {
targets {
jvm()
android()
}
sourceSets {
jvmMain {
dependencies {
api kotlin("stdlib-common")
api kotlin("stdlib-jdk8")
}
}
androidMain {
dependsOn jvmMain
}
}
}
android {
compileSdkVersion 28
sourceSets {
main {
java.srcDirs += "src/jvmMain/kotlin" // Android target recognizes Java with this
manifest.srcFile "src/androidMain/AndroidManifest.xml"
}
}
}
I am pretty sure it’s something simple with my gradle file. Many thanks for your help guys.
Another workaround the issue without losing the ability to generate an android archive .aar
for the library1
would be to make a new version of this same library depending on precompiled artefacts of a splitted version of the original library1
.
So you would end up with a multi-module gradle project, something like this:
You could use whatever you prefer to publish those artefacts, but a local maven repo
should work just fine!
That would mean replacing:
kotlin {
targets {
jvm()
android()
}
sourceSets {
jvmMain {
dependencies {
api kotlin("stdlib-common")
api kotlin("stdlib-jdk8")
}
}
androidMain {
dependsOn jvmMain
}
}
}
with:
kotlin {
targets {
jvm()
android()
}
sourceSets {
jvmMain {
dependencies {
api kotlin("stdlib-common")
api kotlin("stdlib-jdk8")
api "com.company:library-jvm:1.0.0"
}
}
androidMain {
dependsOn jvmMain
dependencies {
api "com.company:library-android:1.0.0"
}
}
}
}
That way, you don't need the java plugin at all in the final library1
, because all the java code will already be built in a separate step.
Hence library1
could keep both the JVM
and Android
targets
In order to fix your issue, you need to:
Error: The 'java' plugin has been applied, but it is not compatible with the Android plugins
library1
project if you want your JVM target to recognize your Java source files.java
of the kotlin
source roots.More infos: Kotlin docs for java-support-in-jvm-targets
I also created a pull request solving your issue.
The downside of this approach is that you will not be able to generate an android archive .aar
for the library1
, but I guess using the java archive .jar
in your android project should not be a problem at all.
library1/build.gradle:
apply plugin: "kotlin-multiplatform"
kotlin {
jvm {
withJava()
}
sourceSets {
jvmMain {
dependencies {
api kotlin("stdlib-common")
api kotlin("stdlib-jdk8")
}
}
}
}
library2/build.gradle:
apply plugin: "kotlin-multiplatform"
apply plugin: "com.android.library"
kotlin{
jvm()
android()
sourceSets {
jvmMain.dependencies {
api project(":library1")
}
androidMain {
dependsOn jvmMain
}
}
}
android {
compileSdkVersion 28
sourceSets {
main {
java.srcDirs += "src/jvmMain/kotlin"
manifest.srcFile "src/androidMain/AndroidManifest.xml"
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With