如何阻止ProGuard修改Android库中Kotlin suspend函数签名?
解决Kotlin Suspend方法在ProGuard处理后签名失效的问题
问题背景
为Android库编写了包含suspend方法的Kotlin接口作为Facade:
interface Facade { suspend fun doSomeWork(): String }
添加ProGuard规则尝试保留该接口:
-keep interface com.some.library.Facade { *; }
但接入应用后无法以suspend函数方式调用doSomeWork,反编译发现方法签名被修改为:
public interface Facade { @Nullable Object doSomeWork(@NotNull Continuation<? super String> var1); }
禁用ProGuard则一切正常。
已尝试的无效方案
- 添加
-keepattributes Signature,LineNumberTable,RuntimeVisibleAnnotations,AnnotationDefault,Code - 保留整个包
-keep com.some.library.** { *; } - 保留Kotlin相关类
-keep class kotlin.** { *; }和-keep class kotlinx.** { *; } - 替换ProGuard配置文件为
proguard-android.txt - 禁用R8 full模式
android.enableR8.fullMode=false
正确解决方案
调整ProGuard规则
需要同时保留接口方法的完整签名,以及Kotlin识别suspend方法所需的元数据属性:
# 保留Facade接口及其所有方法的完整签名(包括泛型参数) -keep interface com.some.library.Facade { <methods>; } # 保留关键属性,确保Kotlin能解析suspend方法的元数据 -keepattributes Signature, RuntimeVisibleParameterAnnotations, RuntimeVisibleAnnotations
规则解释
<methods>相较于*更明确地保留方法的完整签名,包括参数的泛型信息——suspend函数的返回类型依赖于Continuation<? super String>中的泛型参数,这是Kotlin识别suspend方法的核心。Signature属性用于保留泛型类型信息,缺失后Kotlin无法关联字节码方法与原suspend函数的返回值类型。RuntimeVisibleParameterAnnotations和RuntimeVisibleAnnotations保留参数和方法的注解(比如@NotNull),这些注解是Kotlin编译器验证suspend方法签名的必要信息。
补充说明
如果使用R8(AGP默认的混淆工具),确保没有额外开启会移除泛型或注解的优化规则。上述规则已经覆盖了R8和ProGuard的核心需求,无需单独保留整个Kotlin类库。
内容的提问来源于stack exchange,提问作者Roman Svyatnenko
相关产品推荐
相关产品推荐

