Android Kotlin ProGuard 规则错误?
Posted
技术标签:
【中文标题】Android Kotlin ProGuard 规则错误?【英文标题】:Android Kotlin ProGuard Rules Wrong? 【发布时间】: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
【问题讨论】:
【参考方案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$** *;
【讨论】:
以上是关于Android Kotlin ProGuard 规则错误?的主要内容,如果未能解决你的问题,请参考以下文章