android studio自带java语言的ProGuard工具,主要用来压缩、优化、混淆,然后配合Gradle构建工具实现混淆。
在app module中统一配置混淆规则
我们可以直接在app module中build.gradle文件配置所有module需要混淆的规则。这样,其他module中就无需开启混淆。
首先在build.gradle 中将混淆的开关打开,即 minifyEnabled 置为 true
buildTypes {
release {
minifyEnabled true //开启混淆
zipAlignEnabled true //压缩优化
shrinkResources true //移出无用资源
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' //默认的混淆文件以及我们指定的混淆文件
}
}
如果是model混淆,子模块混淆文件的指定是通过consumerProguardFiles这个属性来指定的,并不是proguardFiles 属性,而且我们无需配置其他的选项,只需要配置consumerProguardFiles属性就可以。该属性表示在打包的时候会自动寻找该module下我们指定的混淆文件对代码进行混淆。配置如下:
buildTypes {
release {
//minifyEnabled true //是否开启混淆,其实子模块中这个已经没有作用了,由主模块控制
consumerProguardFiles 'proguard-rules.pro' //子模块要用这个命令才能生效
}
然后就要去proguard-rules.pro写入我们的混淆的规则(如文件其名),防止重要的类被混淆移除了。
先特别介绍的是与保持相关元素不参与混淆的规则相关的几种命令:
-keep 防止类和成员被移除或者被重命名
-keepnames 防止类和成员被重命名
-keepclassmembers 防止成员被移除或者被重命名
-keepclasseswithmembers 防止拥有该成员的类和成员被移除或者被重命名
-keepclasseswithmembernames 防止拥有该成员的类和成员被重命名
混淆规则:
1、有一些固定的混淆规则不需要更改:
#指定代码的压缩级别
-optimizationpasses 5
#包明不混合大小写
-dontusemixedcaseclassnames
#不去忽略非公共的库类
-dontskipnonpubliclibraryclasses
#优化 不优化输入的类文件
-dontoptimize
#预校验
-dontpreverify
#混淆时是否记录日志
-verbose
# 混淆时所采用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#保护注解
-keepattributes *Annotation*
2、理解通配符
-keep class cn.hadcn.test.**
-keep class cn.hadcn.test.*
很多同学都搞不懂下面两个的区别,一颗星表示只是保持该包下的类名,而子包下的类名还是会被混淆;两颗星表示把本包和所含子包下的类名都保持;用以上方法保持类后,你会发现类名虽然未混淆,但里面的具体方法和变量命名还是变了,这时如果既想保持类名,又想保持里面的内容不被混淆,我们就需要以下方法了:
-keep class cn.hadcn.test.* {*;}
3、保证指定包名下的所有类及子包中所有的类不被混淆
例子1:com.lib.manager 包下面的类不混淆
-keep class com.lib.manager.**{*;}
例子2:v4包下面的所有类不混淆
-keep class android.support.v4.** { *; }
4、保证指定的类不被混淆
例子1:YiBaWiFiActivity 类不被混淆, YiBaWiFiActivity 完整包名:com.yiba.wifi.sdk.lib.activity.YiBaWiFiActivity
-keep class com.yiba.wifi.sdk.lib.activity.YiBaWiFiActivity{*;}
例子2:v4 包下面的 ActivityCompat 类不被混淆
-keep class android.support.v4.app.ActivityCompat{*;}
5、不混淆指定类的子类
-keep class * extends pp.lib.User { *; }
User 类的子类不混淆
6、指定接口不混淆
Callback 是一个接口,完整包名为:com.lib.impl.Callback
-keep interface com.lib.impl.Callback{ * ; }
7、指定接口的实现类不混淆
Callback 是一个接口,完整包名为:com.lib.impl.Callback . 所有的实现类都不会混淆。
-keep class * implements com.lib.impl.Callback { *; }
8、指定类的内部类不混淆
PhoneUtil 的源码如下:
package com.lib.manager;
import android.content.Context;
import android.os.AsyncTask;
/**
* Created by yiba_zyj on 2017/4/5.
*/
public class PhoneUtil {
public final static int APPID = 100 ;
public PhoneUtil( Context context ){
}
class MyTask extends AsyncTask {
@Override
protected Object doInBackground(Object[] params) {
return null;
}
}
}
PhoneUtil 有一个常量、一个构造函数、一个内部类.
混淆规则:
-keep class com.lib.manager.PhoneUtil$* {
* ;
}
9、构造函数不混淆
PhoneUtil 的源码如所示: