处理 R8 + JvmStatic Annotation + Lambda in public API for Android Library written in Kotlin
Dealing with R8 + JvmStatic Annotation + Lambda in public API for Android Library written in Kotlin
首先,请注意,我并不期待 why do you want to obfuscate library
评论。这是我要问的一个真正的问题。
我在使用 Kotlin 编写的 Android 库处理 R8/obfuscation 时遇到了问题。
我有一个 public API 方法,它用 @JvmStatic
注释并且该方法采用 Lambda
作为参数。
例如,看看下面的代码,
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: The method 'void setCallback(kotlin.jvm.functions.Function2)' was expected to be of type virtual but instead was found to be of type static (declaration of 'com.demo.basic.Application' appears in /data/app/com.demo.basic-_0uJXPbtfs3UZ2Rp2h-RdQ==/base.apk!classes2.dex)
我是不是在某处犯了错误,或者这应该是某种限制?
我尝试了什么?
删除 @Jvmstatic
解决了问题,但它创建了难看的 Java 调用代码
保留 @Jvmstatic
但删除 Lambda
将 Lambda 转换为 interface with one method
,一切正常。不幸的是 SAM for Kotlin classes
还没有,所以调用 Kotlin
代码看起来很难看。
这在 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.
}
R8 团队在 R8 版本 2.1.42
中有 fixed this issue along with related issue b/158400283
修复程序应该已经在 Android Studio 4.1 beta
或更高版本中可用,但如果您使用的是稳定版 Android Studio 4.0
,则将以下内容添加到您的顶级 build.gradle 文件中:
buildscript {
repositories {
maven {
url 'https://storage.googleapis.com/r8-releases/raw'
}
}
dependencies {
classpath 'com.android.tools:r8:2.1.42' // Must be before the Gradle Plugin for Android.
classpath 'com.android.tools.build:gradle:X.Y.Z' // Your current AGP version.
}
}
首先,请注意,我并不期待 why do you want to obfuscate library
评论。这是我要问的一个真正的问题。
我在使用 Kotlin 编写的 Android 库处理 R8/obfuscation 时遇到了问题。
我有一个 public API 方法,它用 @JvmStatic
注释并且该方法采用 Lambda
作为参数。
例如,看看下面的代码,
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: The method 'void setCallback(kotlin.jvm.functions.Function2)' was expected to be of type virtual but instead was found to be of type static (declaration of 'com.demo.basic.Application' appears in /data/app/com.demo.basic-_0uJXPbtfs3UZ2Rp2h-RdQ==/base.apk!classes2.dex)
我是不是在某处犯了错误,或者这应该是某种限制?
我尝试了什么?
删除
@Jvmstatic
解决了问题,但它创建了难看的 Java 调用代码保留
@Jvmstatic
但删除Lambda
将 Lambda 转换为interface with one method
,一切正常。不幸的是SAM for Kotlin classes
还没有,所以调用Kotlin
代码看起来很难看。
这在 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.
}
R8 团队在 R8 版本 2.1.42
修复程序应该已经在 Android Studio 4.1 beta
或更高版本中可用,但如果您使用的是稳定版 Android Studio 4.0
,则将以下内容添加到您的顶级 build.gradle 文件中:
buildscript {
repositories {
maven {
url 'https://storage.googleapis.com/r8-releases/raw'
}
}
dependencies {
classpath 'com.android.tools:r8:2.1.42' // Must be before the Gradle Plugin for Android.
classpath 'com.android.tools.build:gradle:X.Y.Z' // Your current AGP version.
}
}