【发布时间】:2017-05-21 11:10:07
【问题描述】:
我正在开发一款使用 LibGDX 游戏框架的游戏。目前我的目标平台是通过独立于平台的 jar 和 Android 的桌面(PC、Mac、Linux)。
该项目托管在https://github.com/NoxHarmonium/project-whiplash,如果需要,请随时查看。
大部分代码位于一个名为 core 的模块中,并且完全用 Kotlin 编写。此模块链接到桌面和 Android 项目。
这适用于 Android 版本 7.1+ 和桌面。对于所有其他版本的 Android,我会在匿名函数上收到一堆 java.lang.NoClassDefFoundError 异常,例如:
val objectObservable = this.observableCache.computeIfAbsent(assetRef, fun(assetRef: AssetRef): Observable<T> {
return Async.start(fun(): T {
...
}).observeOn(this.eventLoopScheduler)
})
异常示例:
java.lang.NoClassDefFoundError: com.projectwhiplash.utils.assets.LibGdxDataManager$objectMapFromYaml$objectMapObservable$1
这似乎是由于与 Kotlin 默认针对的 JVM (1.8) 和旧版本 Android 支持的 JVM 级别 (1.6) 不兼容造成的。我可能是错的,但这解释了为什么最新版本的 Android 可以工作,因为它支持更高版本的 JVM。
解决方案应该像强制 Kotlin 像 1.6 版一样发出 JVM 字节码一样简单,但我似乎无法解决。如果直接将 Kotlin 编译到 Android 中,这似乎是通过使用 kotlin-android Gradle 插件来处理的。不幸的是,我不能将这个插件用于核心模块,因为它不应该有任何 Android 依赖项。
我尝试使用https://kotlinlang.org/docs/reference/using-gradle.html#compiler-options 中提到的构建设置覆盖 JVM 版本,如下所示:
compileKotlin {
kotlinOptions {
jvmTarget = "1.6"
}
}
但是,无论我将它放在哪个 Gradle 文件中,它似乎都不起作用。事实上,当我尝试它时,Intellij 显示“无法解析符号 'kotlinOptions'”错误。可能是 Kotlin 团队更改了某些内容,而文档尚未更新。
我可以在 Intellij 模块设置中手动覆盖 Kotlin 设置,但每次同步 gradle 项目时都会被覆盖,这不是一个好的长期解决方案。该项目旨在独立于 IDE。
有谁知道我如何设置核心模块以最大程度地兼容旧版本的 Android?
我目前将最低 API 级别设置为 9,因为这是当前 LibGDX 的默认值,但如果定位如此低的 API 级别太困难,我愿意将其设置得更高。
编辑 1:
我刚刚提取了核心模块生成的 jar 文件,并使用javap 工具检查了类文件。
我在一个随机的类文件上运行了以下命令
java -verbose foo.class
它会输出带有以下文本的文本
...
minor version: 0
major version: 50
...
使用这个问题List of Java class file format major version numbers?我确定类文件实际上是针对JVM 1.6。
因此,我最初的理论是错误的,还有另一个原因是旧 Android 版本无法加载由 Kotlin lambdas 生成的类。
【问题讨论】:
标签: android intellij-idea gradle libgdx kotlin