一 开启混淆
minifyEnabled true 设置为true
并在项目根目录建立proguard-android.txt的文件
android {
buildTypes {
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-unity.txt'
jniDebuggable true
signingConfig signingConfigs.debug
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-unity.txt'
signingConfig signingConfigs.debug
}
}
}
二 混淆逻辑配置
proguard-android.txt
1混淆的功能
proguard包括四个功能,shrinker(压缩), optimizer(优化),obfuscator(混淆),preverifier(预校验),他们的作用分别是:
shrink: 检测并移除没有用到的类,变量,方法和属性;
optimize: 优化代码,非入口节点类会加上private/static/final, 在字节码级别执行优化,让应用运行的更快。。
obfuscate: 增大反编译难度,类和类成员会被随机命名,除非用keep保护。
preverify: 预校验代码是否符合Java1.6或者更高的规范.
2关闭方法
3 如果开启混淆,简单的例子
这里只写一些简单的obfuscate
保留混淆包 -keep
-keep class com.unity3d.player.* { *; }
-keep class com.unity3d.player.* # 一颗星只保持本包的类名(不包含内容)
-keep class com.unity3d.player.** # 二颗星表示保持本包和子包下的类名(不包含内容)
保留混淆的类 -keepclasseswithmembers //因为开启混淆后, 不被引用的方法会被丢弃掉
-keepclasseswithmembers class com.*****.cn.UnityPlayerActivity{
public void commLogin(java.lang.String);
}
4 注意事项
1,jni方法不可混淆,因为这个方法需要和native方法保持一致;
-keepclasseswithmembernamesclass*{# 保持native方法不被混淆 native ;}
2,反射用到的类不混淆(否则反射可能出现问题);
3,AndroidMainfest中的类不混淆,所以四大组件和Application的子类和Framework层下所有的类默认不会进行混淆。自定义的View默认也不会被混淆;所以像网上贴的很多排除自定义View,或四大组件被混淆的规则在Android Studio中是无需加入的;
4,与服务端交互时,使用GSON、fastjson等框架解析服务端数据时,所写的JSON对象类不混淆,否则无法将JSON解析成对应的对象;
5,使用第三方开源库或者引用其他第三方的SDK包时,如果有特别要求,也需要在混淆文件中加入对应的混淆规则;
6,有用到WebView的JS调用也需要保证写的接口方法不混淆,原因和第一条一样;
7,Parcelable的子类和Creator静态成员变量不混淆,否则会产生Android.os.BadParcelableException异常;
-keepclass*implementsAndroid.os.Parcelable{# 保持Parcelable不被混淆 publicstaticfinalAndroid.os.Parcelable$Creator *;}
8,使用enum类型时需要注意避免以下两个方法混淆,因为enum类的特殊性,以下两个方法会被反射调用。
-keepclassmembersenum* {publicstatic**[] values();publicstatic**valueOf(java.lang.String); }
5 资料参考:
1.http://proguard.sourceforge.net/
2.http://developer.android.com/tools/help/proguard.html
三 垃圾代码制造
android.applicationVariants.all { variant ->
androidJunkCode.configMap.put(variant.name, {
packageBase = "com.abc.game" //生成java类根包名
packageCount = 30 //生成包数量
activityCountPerPackage = 3 //每个包下生成Activity类数量
otherCountPerPackage = 50 //每个包下生成其它类的数量
methodCountPerClass = 20 //每个类下生成方法数量
resPrefix = "color_" //生成的layout、drawable、string等资源名前缀
drawableCount = 300 //生成drawable资源数量
stringCount = 300 //生成string数量
})
}
反编译后的效果
混淆项目的示例下载地址
根目录的build.gradle中:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "com.github.qq549631030:android-junk-code:1.1.2"
}
}
app目录的build.gradle模块中:
apply plugin: 'com.android.application'
apply plugin: 'android-junk-code'
androidJunkCode {
variantConfig {
release {//变体名称,如果没有设置productFlavors就是buildType名称,如果有设置productFlavors就是flavor+buildType,例如(freeRelease、proRelease)
packageBase = "cn.hx.plugin.ui" //生成java类根包名
packageCount = 30 //生成包数量
activityCountPerPackage = 3 //每个包下生成Activity类数量
excludeActivityJavaFile = false //是否排除生成Activity的Java文件,默认false(layout和写入AndroidManifest.xml还会执行),主要用于处理类似神策全埋点编译过慢问题
otherCountPerPackage = 50 //每个包下生成其它类的数量
methodCountPerClass = 20 //每个类下生成方法数量
resPrefix = "junk_" //生成的layout、drawable、string等资源名前缀
drawableCount = 300 //生成drawable资源数量
stringCount = 300 //生成string数量
}
}
}