Hi.
I’m trying to create a shared library using Kotlin Native that will be used on Android and iOS.
I tried creating something simple just to check if it works and it partially did, partially didn’t.
- In Kotlin Native common source set, I’ve created a simple class (let’s say:
Printer
) with a simple function that prints anything usingprintln
(let’s say:printSomething
). - Built the project and got 3 jars as a result (like:
printer-jvm-0.0.1.jar
,printer-metadata-0.0.1.jar
andprinter-metadata-0.0.1-sources.jar
) - Manually copy-pasted the jars to the Android app’s
libs
directory. - In Android app code, created an object and executed the printing function (like:
Printer().printSomething()
) - so far so good.
But since I need some kind of BigDecimal
-like support in Kotlin Native library, I tried to use some external library to check how it is going to work like.
I imported it like this:
commonMain {
dependencies {
implementation kotlin('stdlib-common')
implementation("com.ionspin.kotlin:bignum:0.1.6-1.3.72-SNAPSHOT")
}
}
And I added something like this in my Kotlin Native common source set:
import com.ionspin.kotlin.bignum.decimal.BigDecimal
import com.ionspin.kotlin.bignum.decimal.DecimalMode
import com.ionspin.kotlin.bignum.decimal.RoundingMode
data class Percentage(val value: String) {
val half get() = BigDecimal.parseStringWithMode(
value,
DecimalMode(
decimalPrecision = 2,
roundingMode = RoundingMode.ROUND_HALF_CEILING
)
).toStringExpanded()
}
Then, in the Android app, I was able to write:
Percentage("1.00").half
But when the app was running and I executed that line of code, the app crashed:
07-23 15:54:51.868 4591-4591/com.example.app.stage E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.app.stage, PID: 4591
java.lang.NoClassDefFoundError: Failed resolution of: Lcom/ionspin/kotlin/bignum/decimal/BigDecimal;
at sample.Percentage.getHalf(Percentage.kt:8)
at com.example.app.ui.SimpleViewModel.saveOrder(SimpleViewModel.kt:296)
at com.example.app.ui.SimpleFragment$onViewCreated$4.invoke(SimpleFragment.kt:144)
at com.example.app.ui.SimpleFragment$onViewCreated$4.invoke(SimpleFragment.kt:54)
at com.example.app.ui.view.list.ListContainer$2.onClick(ListContainer.kt:48)
at android.view.View.performClick(View.java:4780)
at android.view.View$PerformClick.run(View.java:19866)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.ionspin.kotlin.bignum.decimal.BigDecimal" on path: DexPathList[[zip file "/data/app/com.example.app.stage-1/base.apk"],nativeLibraryDirectories=[/data/app/com.example.app.stage-1/lib/x86_64, /vendor/lib64, /system/lib64]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
at sample.Percentage.getHalf(Percentage.kt:8)
at com.example.app.ui.SimpleViewModel.saveOrder(SimpleViewModel.kt:296)
at com.example.app.ui.SimpleFragment$onViewCreated$4.invoke(SimpleFragment.kt:144)
at com.example.app.ui.SimpleFragment$onViewCreated$4.invoke(SimpleFragment.kt:54)
at com.example.app.ui.view.list.ListContainer$2.onClick(ListContainer.kt:48)
at android.view.View.performClick(View.java:4780)
at android.view.View$PerformClick.run(View.java:19866)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Suppressed: java.lang.ClassNotFoundException: com.ionspin.kotlin.bignum.decimal.BigDecimal
at java.lang.Class.classForName(Native Method)
at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
... 16 more
Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available
So I guess the jars produced by the Kotlin Native build do not include the dependencies for some reason and I have no clue what to do about it.
This is my whole build.gradle
file in the Kotlin Native project (it was generated like this by IntelliJ IDEA, the only thing I changed was adding the dependency on the external Kotlin Native library for the BigDecimal
s).
plugins {
id 'org.jetbrains.kotlin.multiplatform' version '1.3.72'
}
repositories {
mavenCentral()
maven {
url = uri("https://oss.sonatype.org/content/repositories/snapshots")
}
}
group 'com.example'
version '0.0.1'
apply plugin: 'maven-publish'
kotlin {
jvm()
// This is for iPhone simulator
// Switch here to iosArm64 (or iosArm32) to build library for iPhone device
iosX64("ios") {
binaries {
framework()
}
}
sourceSets {
commonMain {
dependencies {
implementation kotlin('stdlib-common')
api("com.ionspin.kotlin:bignum:0.1.6-1.3.72-SNAPSHOT")
}
}
commonTest {
dependencies {
implementation kotlin('test-common')
implementation kotlin('test-annotations-common')
}
}
jvmMain {
dependencies {
implementation kotlin('stdlib')
}
}
jvmTest {
dependencies {
implementation kotlin('test')
implementation kotlin('test-junit')
}
}
iosMain {
}
iosTest {
}
}
}
configurations {
compileClasspath
}
Is this issue caused by some missing configuration in Gradle? Or do I have to do something specific on the Android app’s side to be able to use the jars produced by the Kotlin Native build? Or something else?