个人技术总结——Proguard Rules配置经验总结

222200127徐煜晖 2024-12-09 11:48:58

个人技术总结——Proguard Rules配置经验总结

这个作业属于哪个课程https://bbs.csdn.net/forums/2401_CS_SE_FZU
这个作业要求在哪里https://bbs.csdn.net/topics/619470310
这个作业的目标个人技术总结
其他参考文献

目录

  • 个人技术总结——Proguard Rules配置经验总结
  • 概述
  • 技术用途
  • 使用原因
  • 技术难点
  • 详述
  • 流程图
  • 步骤
  • 1. 启用minify
  • 2. 编译与测试
  • 3. 配置规则
  • 实体类通过反射序列化/反序列化
  • 以 ViewBinding 基类为代表的泛型传递
  • 第三方库的混淆规则
  • 问题与解决
  • 问题描述
  • 排查过程
  • 问题解决
  • 总结
  • 参考文献

概述

技术用途

代码混淆具有三大主要好处,一是降低apk包体体积;二是降低smali可读性,缓解反编译带来的安全风险;三是降低dex数目,加快运行速度。

代码混淆的简要工作原理是:

  1. 通过tree shake的方式,抛弃不需要的代码,降低dex体积。
  2. 通过重命名的方式,将类名、变量名、方法名缩短,而不影响运行结果。

使用原因

本次新苗同学App开发后期优化过程中,观测到App包体较大,对于成本控制和用户体验等方面都有不良影响。因此,决定启用代码混淆解决此问题。

技术难点

混淆规则(Proguard Rules)需要结合项目情况手工配置,没有统一解,异常情况需要自行分析日志解决。

详述

流程图

img

步骤

1. 启用minify

在app级的build.gradle.kts中,修改release类型的配置,开启minify并指定规则文件为同级目录下proguard-rules.pro文件。

buildTypes {
    release {
        isMinifyEnabled = true
        proguardFiles(
            getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
        )
    }
}

2. 编译与测试

在左侧栏Build Variants中,切换Active Build Variant为release,执行Gradle Build任务并进行安装,测试是否出现闪退、数据不正常的情况。

3. 配置规则

对症下药,配置对应规则,重新进行编译测试。

经过测试,总结出几种常用规则如下:

实体类通过反射序列化/反序列化

开发中经常遇到json与实体类互转的情况,通常会用到Gson,kotlinx.serialization等三方库来实现。其底层是通过反射实现的。反射即通过类名/变量名等的字符串找到对应的类/变量,并通过相应的机制赋值之。

从前述可知,shrink后类名以及类成员名称可能发生改变,所以从json转为实例类的时候就会出现json对应的key在实例中找不到的情况,从实例类转json出现json的key变乱码的情况。

规则也很简单,keep住对应包下的所有类即可。

-keep class com.example.data.** { *; }

如果是用kotlinx.serialization进行实体类的注解,可以用下面规则:

-keep public class * implements java.io.Serializable {*;}
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}
以 ViewBinding 基类为代表的泛型传递

为了复用的便利,我们经常会定义BaseActivity、BaseFragment等,通过泛型传入binding class,并在基类做初始化。泛型在minify中默认会被抹除,导致运行失败。处理手段是keep住ViewBinding实现类以及继承基类的类。

-keepattributes Signature # 泛型
-keep,allowobfuscation class * implements androidx.viewbinding.ViewBinding { *; }
-keepclassmembers class * implements androidx.viewbinding.ViewBinding { *; }
-keep,allowobfuscation class com.example.base.ui.** { *; }
-keep,allowobfuscation class * extends com.example.base.ui.** { *; }
第三方库的混淆规则

现在先进一点的三方库会自带规则,如果没有的话需要看对应的README去添加上,常见于一些商业性质的库。

问题与解决

问题描述

在排查 ViewBinding 混淆问题时,发现部分binding类在Signature中变为了Object类,导致运行失败。

排查过程

用Android Studio打开apk,加载mapping文件,查看到混淆前后的映射:

img

查看编译后指定类的字节码:

img

img

proguard.rules中配置输出被r8优化掉的类情况:

-printusage r8usage.txt

问题解决

排查发现,r8将部分ViewBinding类移除了。查看对应规则,发现ViewBinding类的规则头部写成了

-keep,allowobfuscation,allowshrinking

即意味着允许shrink掉r8不使用的类,而通过反射实现的ViewBinding调用导致了误判。按如下修改得到解决。

-keep,allowobfuscation

总结

很难避免开启minify后App运行异常甚至闪退的情况,这时候需要认真查看crash log去定位,必要时需了解一些smali知识。往往排查问题所在才是最耗时的。

参考文献

《Proguard Rules 配置经验总结》,作者徐煜晖:https://www.klxiaoniu.top/android/proguard.html

...全文
1957 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

109

社区成员

发帖
与我相关
我的任务
社区描述
202401_CS_SE_FZU
软件工程 高校
社区管理员
  • FZU_SE_TeacherL
  • 言1837
  • 助教姜词杰
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧