首页 > 解决方案 > 在用 Kotlin 编写的 Android 库的公共 API 中处理 R8 + JvmStatic Annotation + Lambda

问题描述

首先,请注意,我不期待why do you want to obfuscate library评论。这是我要问的一个真正的问题。

我在使用 Kotlin 编写的 Android 库处理 R8/混淆时遇到问题。

我有一个带有注释的公共 API 方法,@JvmStatic该方法采用Lambdaas 参数。

例如,看看下面的代码,

typealias MyLambdaCallback = (String, Map<String, Any>) -> Unit

@Keep
object MyApi {

    private var callback: MyLambdaCallback? = null

    @JvmStatic
    fun setCallback(callback: MyLambdaCallback) {
        this.callback = callback
    }
}

我已经添加@Jvmstatic,以便Java调用代码可以静态调用该方法,而不是做MyApi.INSTANCE.setCallback()

当我在没有 的情况下发布库时minification,一切都很好,并且从两者调用代码Java并且Kotlin按预期编写。

但现在我想在打开时释放库minification

这就产生了一个问题。

这是错误

java.lang.IncompatibleClassChangeError:方法 'void setCallback(kotlin.jvm.functions.Function2)' 应该是 virtual 类型,但发现是 static 类型('com.demo.basic.Application' 的声明出现在/data/app/com.demo.basic-_0uJXPbtfs3UZ2Rp2h-RdQ==/base.apk!classes2.dex)

我是在某处犯了错误,还是预期这是某种限制?

我尝试了什么?

  1. 删除@Jvmstatic解决了这个问题,但它创建了丑陋的 Java 调用代码

  2. 保留@Jvmstatic但删除Lambda了将 Lambda 转换为 aninterface with one method并且一切正常。不幸SAM for Kotlin classes的是还没有,所以调用Kotlin代码看起来很难看。

标签: kotlinobfuscationandroid-libraryandroid-r8

解决方案


这在 R8 问题跟踪器http://issuetracker.google.com/158393309上进行了跟踪,其中包含更多详细信息。

简而言之,这已在 R8 版本 2.1.35 中得到修复,可以通过对顶级build.gradle文件进行以下更改来使用它:

repositories {
    maven {
        url 'https://storage.googleapis.com/r8-releases/raw'
    }
}

dependencies {
    classpath 'com.android.tools:r8:2.1.35'          // Must be before the Gradle Plugin for Android.
    classpath 'com.android.tools.build:gradle:X.Y.Z' // Your current AGP version.
 }

推荐阅读