Dealing with R8 + JvmStatic Annotation + Lambda in public API for Android Library written in Kotlin

谁说胖子不能爱 提交于 2021-02-07 05:51:01

问题


First of all, please note that I'm not expecting why do you want to obfuscate library comments. This is a genuine problem I'm asking about.

I have been having an issue dealing with R8/obfuscation with an Android library written in Kotlin.

I've a public API method which is annotated with @JvmStatic and that method takes a Lambda as parameter.

For example, take a look at code below,

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

@Keep
object MyApi {

    private var callback: MyLambdaCallback? = null

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

I have added @Jvmstatic so that Java calling code can call the method statically rather than doing MyApi.INSTANCE.setCallback()

When I release the library without minification, everything is fine and calling code from both Java and Kotlin is written as expected.

But now I want to release the library while turning on minification.

That creates an issue.

Here is the error

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)

Am I making a mistake somewhere or this is expected as some kind of limitation ?

What did I Try ?

  1. Removing @Jvmstatic resolves the issue but it created ugly Java calling code

  2. Kept @Jvmstatic but removed Lambda converting Lambda into an interface with one method and everything is working fine. Unfortunately SAM for Kotlin classes is not there yet, so calling Kotlin code looks ugly.


回答1:


This is tracked on the R8 issue tracker http://issuetracker.google.com/158393309 which has more details.

The short story is that this has been fixed in R8 version 2.1.35, which can be used by making the following changes to the top level build.gradle file:

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.
 }



回答2:


R8 team has fixed this issue along with related issue b/158400283 in R8 version 2.1.42

Fix should already be available in Android Studio 4.1 beta or higher, but if you're using stable Android Studio 4.0 then add following to your top-level build.gradle file:

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.
     }
}


来源:https://stackoverflow.com/questions/62249685/dealing-with-r8-jvmstatic-annotation-lambda-in-public-api-for-android-librar

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!