ProGuard简介
众所周知 java 代码是通过jvm虚拟机把.java文件编译成.class文件,然而.class又很容易被反编译,Android程序也是通过java代码开发,这也就继承了这一点特性,为了防止辛苦码的代码被人拿去套用然后在Android中就出现了混淆这道工序,ProGuard是一个混淆代码的开源项目,它的主要作用是混淆代码,ProGuard主要包括以下4个功能。
- 压缩(Shrink):检测并移除代码中无用的类、字段、方法和特性(Attribute)。
- 优化(Optimize):对字节码进行优化,移除无用的指令。
- 混淆(Obfuscate):使用a,b,c,d这样简短而无意义的名称,对类、字段和方法进行重命名。
- 预检(Preveirfy):在Java平台上对处理后的代码进行预检,确保加载的class文件是可执行的。
总而言之,ProGuard可以帮助我们把无用的代码去掉无形之中就是优化了我们代码,对我们的代码进行压缩减小体积,最主要还是把我们代码混淆可以不那么容易被反编译。
keep 保留,例如keepattributes:表示保留属性
dont 不要,例如dontwarn:表示不要提示警告
ignore 忽略,例如ignorewarning:表示忽略警告
一、基本混淆
# 代码混淆压缩比,在0和7之间,默认为5,一般不需要改
-optimizationpasses 5
# 混淆时不使用大小写混合,混淆后的类名为小写
-dontusemixedcaseclassnames
# 指定不去忽略非公共的库的类
-dontskipnonpubliclibraryclasses
# 指定不去忽略非公共的库的类的成员
-dontskipnonpubliclibraryclassmembers
# 不做预校验,preverify是proguard的4个步骤之一
# Android不需要preverify,去掉这一步可加快混淆速度
-dontpreverify
# 有了verbose这句话,混淆后就会生成映射文件
# 包含有类名->混淆后类名的映射关系
# 然后使用printmapping指定映射文件的名称
-verbose
-printmapping proguardMapping.txt
# 指定混淆时采用的算法,后面的参数是一个过滤器
# 这个过滤器是谷歌推荐的算法,一般不改变
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
# 保护代码中的Annotation(注解)不被混淆
-keepattributes *Annotation*
# 避免混淆泛型
-keepattributes Signature
//抛出异常时保留代码行号,在异常分析中可以方便定位
-keepattributes SourceFile,LineNumberTable
-dontskipnonpubliclibraryclasses
用于告诉ProGuard,不要跳过对非公开类的处理。默认情况下是跳过的,因为程序中不会引用它们,有些情况下人们编写的代码与类库中的类在同一个包下,并且对包中内容加以引用,此时需要加入此条声明。
-dontusemixedcaseclassnames
这个是给Microsoft Windows用户的,因为ProGuard假定使用的操作系统是能区分两个只是大小写不同的文件名,但是Microsoft Windows不是这样的操作系统,所以必须为ProGuard指定-dontusemixedcaseclassnames选项
二、系统包以及不需要被混淆的类
一些继承系统类不需要混淆
-keep public class * extends android.app.Fragment
-keep public class * extends android.app.Activity
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.v4.**
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.preference.Preference
-keep public class * extends android.view.View
# 保留自定义控件(继承自View)不被混淆
-keep public class * extends android.view.View {
*** get*();
void set*(***);
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
}
如果继承TextView,ImageView 等等可将VIew改为对应的父类
# 对于R(资源)下的所有类及其方法,都不能被混淆
-keep class **.R$* {
*;
}
# 保持 native 方法不被混淆
-keepclasseswithmembernames class * {
native <methods>;
}
# 保持枚举 enum 类不被混淆
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# 保留继承 Parcelable 的类不被混淆
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
# 保留继承Serializable序列化的类不被混淆
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
# 保留在类中的成员不被混淆
-keepclassmembernames ExampleActivity
# 保留在类中的成员方法成员名不被混淆(或写成上边那样)
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
# 保留内部类不被混淆(MainActivity替换为对应的外部类)
-keep class com.helloworld.xxx.MainActivity$* { *; }
或者
# 不混淆内部类
-keepattributes InnerClasses
#移除调试的log代码
-assumenosideeffects class android.util.Log {
public static *** v(...);
public static *** i(...);
public static *** d(...);
public static *** w(...);
public static *** e(...);
}
# WebView使用javascript功能则需要开启
-keepclassmembers class fqcn.of.javascript.interface.for.webview {
public *;
}
注:对于Bean类可以采用全部继承一个BaseBean,然后
-keep class * extends BaseBean
,或者方法同一个包下-keep class com.helloworld.**{*;}
三、一些第三方常用框架
Butter Knife(黄油刀)
-project gradle dependencies
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
-module gradle dependencies
compile 'com.jakewharton:butterknife:8.4.0'
apt 'com.jakewharton:butterknife-compiler:8.4.0'
#黄油刀
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
@butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
@butterknife.* <methods>;
}
OkHttp3
# OkHttp3
-dontwarn com.squareup.okhttp3.**
-keep class com.squareup.okhttp3.** { *;}
-dontwarn okio.**
Retrofit+RxJava+RxAndroid
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'io.reactivex:rxandroid:1.2.1'
compile 'io.reactivex:rxjava:1.1.6'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
Retrofit
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
#泛型与反射
-keepattributes Signature
-keepattributes EnclosingMethod
RxJava&RxAndroid
-dontwarn sun.misc.**
-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
long producerIndex;
long consumerIndex;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
rx.internal.util.atomic.LinkedQueueNode producerNode;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
rx.internal.util.atomic.LinkedQueueNode consumerNode;
}
至于其他的三方框架可以去对应官网去copy。