【问题标题】:Android Kotlin ProGuard Rules Wrong?Android Kotlin ProGuard 规则错误?
【发布时间】:2020-11-11 08:27:38
【问题描述】:

目前我有一个可供多个其他项目使用的库,但是在使用 .aar 时遇到代码混淆问题,尤其是在某些类中:

这个用于处理后端响应或异步任务等。

sealed class Result<out T : Any> {
    open class Success<out T : Any>(val data: T) : Result<T>()
    open class Error(val error: ErrorModel) : Result<Nothing>()
}

这个可以作为库的初始化器或类似的东西:

class LibApp private constructor(
    val appContext: Context
) {

    companion object {
        @JvmStatic lateinit var instance: LibApp
            private set

        fun init(
            appContext: Context
        ) {
            if (this::instance.isInitialized.not()) {
                instance = LibApp(appContext)
            }
        }
    }
}

我使用的规则是:

#noinspection ShrinkerUnresolvedReference
-keep class com.cross.project.compilation.testlib.response.** { *; }
-keep class com.cross.project.compilation.testlib.LibApp.** { *; }

目前我有 3 种构建类型和 2 种风格:

buildTypes {
        release {
            debuggable false
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }

        releaseDebug{
            debuggable true
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }

        debug{
            debuggable true
            minifyEnabled false
        }
    }

    flavorDimensions "libFlavors"

    productFlavors {

        dev {

        }

        prod {

        }

    }

当我检查消费者项目中的发布变体的反编译源时,我得到:

Result 从 Success 返回中获取

public sealed class Result<out T : kotlin.Any> private constructor() {
    public open class Error public constructor(error: com.cross.project.compilation.testlib.response.ErrorModel) : com.cross.project.compilation.testlib.response.Result {
        public final val error: com.cross.project.compilation.testlib.response.ErrorModel /* compiled code */
    }

    public open class Success<out T : kotlin.Any> public constructor(data: T) : com.cross.project.compilation.testlib.response.Result {
        public final val data: T /* compiled code */
    }
}

这改变了变体中的编码方式,类似于 dev 中的代码:

 return when (val response = accountService.getAccountData()) {
            is Result.Success -> ConsumerResult.Success(response.data)
            is Result.ErrorModel -> ConsumerResult.Failure(response.errorModel)
        }

到这里:

 return when (val response = accountService.getAccountData()) {
            is Result.Success<*> -> ConsumerResult.Success((response.data as AccountData))
            is Result.ErrorModel -> ConsumerResult.Failure(response.errorModel)
        }

LibApp 类由于某种原因被删除。

我尝试修改规则以避免这些问题,但仅通过应用以下内容成功地保留了 LibApp 类:

-keepclasseswithmembers class com.cross.project.compilation.testlib.LibApp {
    public *;
}

-keep @interface kotlin.Metadata {
  *;
}
-keepattributes RuntimeVisibleAnnotations

并且还将@Keep注解添加到类中的每个级别,例如:

@Keep class LibApp private constructor(
    ...

    @Keep
    companion object {
       ...

        @Keep
        fun init(
        ...

但是我没有运气修改规则以保持 Result.Success 的通用返回,知道我做错了什么吗?

作为附加信息,我正在使用和构建 maven-publish 插件:

Android Gradle 插件 4.0.1 Gradle 包装器 6.1.1

这个问题好像是我升级后出现的:

Android Gradle 插件 3.6.3 Gradle 包装器 5.6.4

【问题讨论】:

    标签: android kotlin gradle proguard


    【解决方案1】:

    Result.Error 中的 Nothing 类型在被 R8 混淆时被删除。尝试在 build.gradle 文件中添加以下内容:

    buildscript {
         repositories {
           // other repos are omitted 
            maven { url  'https://storage.googleapis.com/r8-releases/raw' }
        }
        dependencies {
            classpath 'com.android.tools:r8:2.1.68'
            // other dependencies are omitted 
    

    在 proguard 文件中声明 Result 类型以防止混淆

    -keep class [path_to_class].Result { *; }
    -keep class [path_to_class].Result$** { *; }
    

    【讨论】:

      猜你喜欢
      • 2014-11-19
      • 1970-01-01
      • 1970-01-01
      • 2018-02-05
      • 1970-01-01
      • 1970-01-01
      • 2020-01-06
      • 2017-03-04
      • 2015-08-26
      相关资源
      最近更新 更多