最近在需要对所开发的项目进行了代码混淆,在android studio中开启代码混淆其实还是挺方便的,不过因为代码混淆产生的问题非常多,特别是对于一些涉及到反射的第三方库经常因为名称的变化导致无法使用。
下面介绍android studio中对android项目进行代码混淆的详细步骤:
(1)代码混淆开启
想要开启代码混淆功能,只需要在相应的项目中将 build.gradle 的相应设置开启即可。
android{
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
minifyEnable即为开启的开关,而proguard-rules.pro是设置代码混淆时的相关设置,可以过滤不代码混淆的对象。
(2)代码混淆规则设置
程序中每个module下面都有对应的proguard-rules.pro文件,设置其规则可以过滤掉一些类、方法、注解和属性名的混淆,下面是ProGuard的手册页面,详细的规则可以在其中了解。https://stuff.mit.edu/afs/sipb/project/android/sdk/android-sdk-linux/tools/proguard/docs/index.html#manual/introduction.html
下面简单介绍
? 忽略任何单个字母
* 匹配任何不包含分割符的字符串
** 匹配任意字符串
1)忽略混淆类
-keep
[,modifier,...] class_specification
这个语法可以保留类或者成员变量的入口不变,举例如下
-keep public class *{
*;
}
上面这个语法可以匹配任意 public的类以及其成员函数,忽略对其的混淆
-keep class com.example.**{
public static doSomething*(**);
}
com.example下的任意类
2) 忽略类的成员
-keepclassmembers [,modifier,...] class_specification
匹配保留类的成员,如果相应的类被保留,则匹配的成员也会被保留
-keepclassmembers class * implements java.io.Serializable {
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();
}
3)忽略类和类的成员
-keepclasseswithmembers [,modifier,....] class_specification
只有当所有条件都匹配的时候,它的成员变量和类才会避免被混淆
-keepclasseswithmembers public class * {
public static void main(java.lang.String[]);
}
忽略拥有main函数的类的混淆以及main函数的混淆
4)保留类或者成员的名字
-keepnames class_specification
当条件匹配时,忽略混淆匹配的类名和成员名称
-keepnames class * implements java.io.Serializable
5) 保留成员变量的名字
-keepclassmembernames class_specification
当条件匹配时,保留其中匹配的成员变量的名字
6)所有条件匹配时,忽略制定类和成员的名字
-keepclasseswithmembernames class_specification
当类名和类的成员都匹配上时,忽略混淆才起效
其中有几个特别有用的tips, 可以匹配子类或接口:
-keep class AClass extends PClass -keep class CClass implements IClass -keepclassmemberwithmembernames class com.A.B.C.* {
@A.B.C.D <methods>
}
具体更详细的细节,可以参详ProGuard的手册。
(3)常见库的ProGuard设置
EventBus的ProGuard设置
-keepattributes *Annotation*
-keepclassmembers class ** {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; } # Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
<init>(java.lang.Throwable);
}
ButterKnife的ProGuard设置
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; } -keepclasseswithmembernames class * {
@butterknife.* <fields>;
} -keepclasseswithmembernames class * {
@butterknife.* <methods>;
}
LeanCloud的ProGuard设置
# proguard.cfg -keepattributes Signature
-dontwarn com.jcraft.jzlib.**
-keep class com.jcraft.jzlib.** { *;} -dontwarn sun.misc.**
-keep class sun.misc.** { *;} -dontwarn com.alibaba.fastjson.**
-keep class com.alibaba.fastjson.** { *;} -dontwarn sun.security.**
-keep class sun.security.** { *; } -dontwarn com.google.**
-keep class com.google.** { *;} -dontwarn com.avos.**
-keep class com.avos.** { *;} -keep public class android.net.http.SslError
-keep public class android.webkit.WebViewClient -dontwarn android.webkit.WebView
-dontwarn android.net.http.SslError
-dontwarn android.webkit.WebViewClient -dontwarn android.support.** -dontwarn org.apache.**
-keep class org.apache.** { *;} -dontwarn org.jivesoftware.smack.**
-keep class org.jivesoftware.smack.** { *;} -dontwarn com.loopj.**
-keep class com.loopj.** { *;} -dontwarn com.squareup.okhttp.**
-keep class com.squareup.okhttp.** { *;}
-keep interface com.squareup.okhttp.** { *; } -dontwarn okio.** -dontwarn org.xbill.**
-keep class org.xbill.** { *;} -keepattributes *Annotation*
我自己在开发中使用LeanCloud的LeanMessage自定义消息,因为混淆的原因总是解析错误,加上下面两句忽略对继承
com.avos.avoscloud.im.v2.AVIMTypedMessage的混淆即可解决问题,代码如下
-keep class ** extends com.avos.avoscloud.im.v2.AVIMTypedMessage
-keepclassmembers class ** extends com.avos.avoscloud.im.v2.AVIMTypedMessage{
*;
}