生成带混淆配置的aar库

3,101 阅读3分钟
原文链接: www.voidcn.com

今天同事问了一个问题,如何生成带Proguard配置的库,这样在引入的时候就直接从maven或者jcenter引入了,不需要在项目中配置混淆规则了,多贴心的功能啊。但是目前使用的大多数库都要手工加入混淆规则。难道就没有方法了么? 想起前一阵使用的Realm库,里面就不需要手工加规则:

A ProGuard configuration is provided as part of the Realm library. This means that you don’t need to add any Realm specific rules to your ProGuard configuration.

难道Realm有独家秘方?
带着好奇心,开始探究realm源码。
这里写图片描述

这里就是上面解释里自带的混淆规则。继续找
这里写图片描述

看到没consumerProguardFiles属性,它指定了编译时,库自动引入的混淆规则。也就是说应用打包时候会自动的寻找库里的混淆文件,不需要手工配置了。

那么这个属性是咋回事呢? 该属性是在AS的0.5.7版本引入的,目的是让库支持ProGuard。

Proguard support for libraries. Note the current DSL property ‘proguardFiles’ for library now sets the proguard rule file used when proguarding the library code. The new property ‘consumerProguardFiles’ is used to package a rule file inside an aar.

另外在blog.hwangjr.com/2015/11/25/…中也有解释。

consumerProguardFiles

开源库中可以依赖此标志来指定库的混淆方式,此会将*.pro文件打包进入aar中,库混淆时候会自动使用此混淆配置文件。
需要注意的是,以consumerProguardFiles方式加入的混淆具有以下特性:
- *.pro文件会包含在aar文件中
- 这些pro配置会在混淆的时候被使用
- 此配置针对此aar进行混淆配置
- 此配置只对库文件有效,对应用程序无效
所以以AndroidKnife/proguard-config开源库,只要一行代码即可搞定外部混淆:

dependencies { ... compile 'com.hwangjr.proguard:proguardconfig:1.0.1@aar' }

还有guides.codepath.com/android/Bui…中找到了解释。

使用Proguard
如果你打算发布你的正式版,你还应当配置,这样ProGuard会应用到你的库。如果在库配置中指定consumerProguardFiles,ProGuard规则将在编译时期加入。

android {
   defaultConfig {
      minifyEnabled true
      consumerProguardFiles 'consumer-proguard-rules.pro'
   }
}

务必创建一个consumer-proguard-rules.pro。详见配置ProGuard

如果你使用默认配置,ProGuard将混淆并提醒你库类名,使得Android工程不可能引用它们。最确保库类被引入的基本例子如下:

-dontobfuscate
# See https://speakerdeck.com/chalup/proguard 
-optimizations !code/allocation/variable

-keep public class * {
    public protected *;
}

混淆文件的语法详见ProGuard文档。参见这个例子

以上这些适用于aar文件。因为aar文件可包含proguard配置文件。

aar文件可包含如下文件类型:
- /AndroidManifest.xml(强制)
- /class.jar(强制)
- /res/ (强制)
- /R.txt (强制)
- /assets/ (可选)
- /libs/*.jar (可选)
- /jni//*.so (可选)
- /proguard.txt (可选)
- /lint.jar (可选)

最后,其实很多开源项目都使用了这个属性:
这里写图片描述

ConsumerProGuardFilesTest这个git里对配置了混淆规则库的不同编译方式进行了shi’y实验,证明上面的方法是可行的。在编译生成的seeds.txt文件中,找到了库里的类名,未被混淆。
同时在添加Realm库后,realm的类文件也未混淆,同样证明了方法可行。

参考链接: