如何配置ProGuard保留子类伴生对象常量属性并混淆父类对应属性?
问题:能否通过ProGuard暴露子类引用的父类伴生对象常量,同时混淆父类自身的该常量?
代码场景
父类定义(含伴生对象常量):
open class ParentClass { ... companion object { ... const val CONST_PROPERTY = "value" } }
子类ChildClassFromParentClass继承自ParentClass,无额外定义的伴生对象。
业务代码中通过子类访问该常量:
import package.ChildClassFromParentClass class OtherClass { ... private fun doStuff() { val variable = ChildClassFromParentClass.CONST_PROPERTY } ... }
核心疑问
能否配置proguard-rules.pro,让ChildClassFromParentClass.CONST_PROPERTY保持可访问不混淆,但同时混淆ParentClass.CONST_PROPERTY?
已尝试的无效规则
-keepclassmembers class package.ChildClassFromParentClass$** { public static ** Companion; }
解决方案及说明
首先要明确:Kotlin中通过子类访问父类伴生对象成员,只是语法层面的便利,编译后实际还是直接引用父类的伴生对象字段——子类本身不会继承父类的伴生对象,也不会生成自己的Companion实例。你之前的规则无效,就是因为ChildClassFromParentClass根本没有自己的伴生对象。
要实现需求,需配置以下ProGuard规则:
# 1. 保留父类伴生对象的常量字段,确保子类语法调用的底层引用有效 -keepclassmembers class package.ParentClass$Companion { public static final java.lang.String CONST_PROPERTY; } # 2. 保留子类类名,避免业务代码中对子类的引用失效 -keep class package.ChildClassFromParentClass # 3. (可选)若需混淆父类的常量名称,可添加以下规则 # 注意:重命名后需确保所有引用路径一致,建议结合上述-keep规则使用 -renamesourcefileattribute SourceFile -keepattributes SourceFile,LineNumberTable
规则解释
- 第一条规则是核心:因为
ChildClassFromParentClass.CONST_PROPERTY编译后等价于ParentClass.Companion.CONST_PROPERTY,必须保留父类伴生对象的这个字段,否则运行时会抛出NoSuchFieldError。 - 第二条规则保证子类类名不被混淆,避免业务代码中
import package.ChildClassFromParentClass的引用失效。 - 第三条可选规则用于混淆父类常量的名称或隐藏源码信息,若需要完全禁止外部直接通过
ParentClass访问该常量,还可以添加-dontkeep class package.ParentClass,让父类类名被混淆,切断直接引用路径。
内容的提问来源于stack exchange,提问作者Ronie M
相关产品推荐
相关产品推荐

