持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第25天,点击查看活动详情
上一篇文章介绍了,apk的常用的几种瘦身方法,今天就其中的代码混淆,详细介绍下。
首先代码混淆不只是为了瘦身,更重要的是为了我们打包出去的apk文件的代码不被别人反编译出来,直接看到源码,防止我们的一些私密信息或者重要的key泄漏,造成一定的损失。
代码混淆
首先对于代码混淆,我们需要在我们的App目录下的build.gradle文件下开启混淆,但是一般我们只针对我们的release环境,所以在配置的时候,需要注意配置debug环境下不需要混淆,具体的配置如下:
buildTypes {
release {
debuggable true
minifyEnabled Boolean.parseBoolean(needMinify)
zipAlignEnabled Boolean.parseBoolean(needMinify) //zipalign优化
shrinkResources Boolean.parseBoolean(needMinify) // 是否去除无效的资源文件
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
debuggable true
minifyEnabled false
zipAlignEnabled false //zipalign优化
shrinkResources false // 是否去除无效的资源文件
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
这里我们在gradle.properties文件中新增了一个boolean类型的变量来全局控制这个开关。
needMinify = true
配置好开关,接下来我们就可以开始写我们的混淆文件了,配置中的proguard-rules.pro 就是我们混淆代码的存放位置。
一些出常用的配置:
剩下的就是根据自己项目里用到的类或者第三方源码,来配置混淆规则了,这里说到混淆规则,怎么样是混淆的,怎么样是不混淆的呢,这里需要介绍一下混淆的关键字:keep;混淆开启后默认是全部代码混淆,所以如果你不想被混淆的代码就需要通过keep关键字来控制,一般我们不混淆系统的support包还有系统的四大组件内容
# 保留本地native方法不被混淆
-keepclasseswithmembernames class * {
native <methods>;
}
# 保留枚举类不被混淆
-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 *;
}
# 保留继承的
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.annotation.**
#忽略警告
-ignorewarning
# 保留在Activity中的方法参数是view的方法,
# 这样以来我们在layout中写的onClick就不会被影响
-keepclassmembers class * extends android.app.Activity{ public void *(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);
}
#保持 native 方法不被混淆
-keepclasseswithmembernames class * {
native <methods>;
}
#保持 Parcelable 不被混淆
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
#保持 Serializable 不被混淆并且enum 类也不被混淆
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
!static !transient <fields>;
!private <fields>;
!private <methods>;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
#不混淆资源类
-keepclassmembers class **.R$* {
public static <fields>;
}
-keep class **.R$* { *; }
这些是我项目中设置的一些通用的混淆代码。剩下的项目中的混淆,根据自己业务来设置,项目中友盟的混淆:
高德地图,glide等
bugly,eventBus:
# Bugly
-dontwarn com.tencent.bugly.**
-keep class com.tencent.bugly.** {*;}
# EventBus
-keepattributes *Annotation*
-keepclassmembers class ** {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
这些都不参与混淆,第三方很多混淆的规则在他们自己的接入文档中都有,大家在开发中可以自己找下。