Android开启Proguard混淆报构造函数调用方计算错误解决方法
问题场景
- 项目未开启Proguard时运行正常,开启Proguard后抛出异常
- 项目技术栈:Retrofit + Moshi converter + Kotlin Coroutines 拉取列表数据,Hilt实现依赖注入,已手动添加规则保留所有模型类,同时引入了Retrofit、OkHttp、Hilt的官方混淆规则
备注:尝试移除实体类上的Json注解后问题仍然存在
报错信息
Could not compute caller for function: public constructor MovieListEntity(movie_data: kotlin.collections.List<com...domain.entities.MovieData>) defined in com...domain.entities.MovieListEntity[c@dad1eb0] (member = null)
关联实体类代码
data class MovieListEntity( @field:Json(name = "movie_data") val movie_data: List<MovieData> ) data class MovieData( @field:Json(name = "movie_id") val movie_id: Int, @field:Json(name = "sub_title") val sub_title: String, @field:Json(name = "title") val title: String )
当前配置的Proguard规则
-keep class com.***.***.domain.entitie.** { *; } -keep class com.***.***.domain.entities.* -keep class com.***.***.domain.entities.MovieListEntity -keep class com.***.***.domain.entities.MovieData -keep class com.***.***.DataBinderMapperImpl { *; } -keep class com.***.***.DataBinderMapperImpl { *; } -keep class com.***.*****{ public ** component1(); <fields>; }
解决方案
- 首先修正规则拼写错误:第一条规则的包名
com.***.***.domain.entitie.**存在拼写错误(正确包名为entities,少写了末尾的s),导致这条规则完全未生效。 - 替换零散的实体类保留规则,添加Moshi适配Kotlin数据类必须的混淆配置。Moshi通过Kotlin反射查找类的主构造方法完成反序列化,仅保留字段不足以让Moshi识别构造签名,需要替换原有entities相关的零散规则为以下配置:
# 保留Kotlin元数据注解,供Moshi识别类的Kotlin属性签名 -keep class kotlin.Metadata { *; } # 保留domain层实体类的所有构造方法、字段、data class生成的component/copy方法 -keep class com.***.***.domain.entities.** { <init>(...); <fields>; public ** component*(...); public ** copy(...); }
- 如果项目使用Moshi Kotlin CodeGen在编译期生成Json适配器,额外补充以下规则:
-keep class **JsonAdapter { <init>(...); <fields>; } -keepnames @com.squareup.moshi.JsonClass class *
- 删除最后一条范围过宽的
-keep class com.***.*****规则,该规则通配范围不严谨,容易引发类匹配异常,也会导致不必要的类被保留。 - 配置完成后重新编译出release包验证即可,该报错本质是混淆过程中Moshi找不到实体类的主构造方法签名导致的,按上述规则保留构造方法和Kotlin元数据后即可修复。
内容的提问来源于stack exchange,提问作者Islam Ahmed
相关产品推荐
相关产品推荐

