Android Gradle 构建指北 #3 再谈 AAR 与混淆

902

欢迎关注我的公众号 Android高效开发,注重 Android 工程效率与开发体验,涵盖基础架构、Kotlin Multiplatform、Gradle 构建优化等话题,同时也聊聊海外工作生活,推送“二分电台” Podcast 的最新节目。

『构建指北』是探索 Android 构建相关的一系列文章,涵盖了 Gradle、Android Gradle Plugin、Kotlin Script 等工具,以及相关架构上的应用。以发现问题解决问题为出发点,传递新知提高生产效率为落脚点。

之前写了篇文章讲到了由于 buildTypes 默认设置的原因导致 library module 无法 debug 的情况。事实上,当时只解决了打 Debug 包的情况,而忽略了打 Release 包时还埋了一个隐藏的问题。

问题还原:我们在做全局的 rebuild 或者 assembleRelease 时,会出现有些类找不到的情况,而 assembleDebug 不会。仔细观察会发现,这些报错的类都是被外部 module 引用的部分,例如 module A 有类 Clazz,被 module B 引用,则 Clazz 报错。

既然推断是互相引用时才会出问题,那基本可以判断 proguard 出问题了。把 module release 时的 proguard 关掉试试,果然不报错了!回想一下 Android 的打包顺序,应该是这样的:

  1. 分别打包各个的 library module(module 混淆)
  2. 整合解压所有的依赖,包括本地的依赖和远程的依赖,和 application module 一起打整包(整体混淆)

那么,面对不同的情况,应该要有不同的混淆策略:

  • 如果是本地的 library module:可以选择不在 library 做混淆,而只做全局的混淆,这样就不会出现上文的 module 相互引用找不到类的情况,并且只需要维护一份配置文件;

  • 如果是输出到外部的 SDK,一般又分两种:

    • 闭源的:例如高德 SDK,友盟 SDK 等,一般会做 AAR 的混淆,但是会隔离出一个包或者一个类专门提供 API(也就是说明文档里的 API),这个包/类会 keep 住,但是大量的具体的实现会实施混淆,并且尽量把一些敏感内容、算法用 JNI 等方式去做调用。

    • 开源的:例如 Github 上的各类开源库,一般不做 AAR 的混淆,但是会提供一个 consumerProguardFiles 的配置项,用以保证库代码的关键部分不被混淆,如下(参考官方用户指南

      android {
           defaultConfig {
               consumerProguardFiles 'lib-proguard-rules.txt'
           }
           ...
       }
      

欢迎评论点赞,以及关注我的公众号 Android高效开发