混淆
2018/1/8 15:20:48
网站
代码混淆的作用:
打乱代码顺序和改变字符等,保护源代码,防止被他人反编译获得源码。
删除无用的类
Android Studio混淆过程:
点击build.gradle(Module:app)
android {
defaultConfig {
}
buildTypes {
release {
minifyEnabled true // 默认为false 改为true 即为混淆
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' // 混淆代码的配置文件
}
}
}
代码混淆影响到的元素有
- 类名
- 变量名
- 方法名
- 包名
- 其他元素
不能被混淆的文件
四大组件
Bean类
混淆后名称改变,不能通过反射得到对象
第三方的不用混淆
自定义View不能混淆
反射用到的类不能混淆,JNI 方法不混淆
AndroidMainfest 中的类不混淆
四大组件和 Application 的子类和 Framework 层下所有的类默认不会进行混淆
Parcelable 的子类和 Creator 静态成员变量不混淆,否则会产生 android.os.BadParcelableException 异常
使用 GSON、fastjson 等框架时,所写的 JSON 对象类不混淆,否则无法将 JSON 解析成对应的对象
使用第三方开源库或者引用其他第三方的SDK包时,需要在混淆文件中加入对应的混淆规则
有用到 WEBView 的 JS 调用也需要保证写的接口方法不混淆
proguard是什么
Proguard是一个集文件压缩,优化,混淆和校验等功能的工具
它检测并删除无用的类,变量,方法和属性
它优化字节码并删除无用的指令.
它通过将类名,变量名和方法名重命名为无意义的名称实现混淆效果.
最后它还校验处理后的代码
说明
proguardFiles这部分有两段,前一部分代表系统默认的android程序的混淆文件,该文件已经包含了基本的混淆声明,免去了我们很多事,这个文件的目录在
混淆规则
-keep
Keep用来保留Java的元素不进行混淆. keep有很多变种,他们一般都是
- keep
- keepclassmembers
keepclasseswithmembers
-optimizationpasses 5 代码混淆的压缩比例,值在0-7之间 -dontusemixedcaseclassnames 混淆后类名都为小写 -dontskipnonpubliclibraryclasses 指定不去忽略非公共的库的类 -dontskipnonpubliclibraryclassmembers 指定不去忽略非公共的库的类的成员 -dontpreverify 不做预校验的操作 -verbose-printmapping proguardMapping.txt 生成原类名和混淆后的类名的映射文件 -optimizations !code/simplification/cast,!field/*,!class/merging/* 指定混淆是采用的算法 -keepattributes *Annotation*,InnerClasses 不混淆Annotation -keepattributes Signature 不混淆泛型 -keepattributes SourceFile,LineNumberTable 抛出异常时保留代码行号 基本指令区基本介绍完了,说下2条用的最多的指令 -keep class XXXX 保留类名不变,也就是类名不混淆,而类中的成员名不保证。当然也可以是继承XXX类的所有类名不混淆,具体代码不贴了,重在理解。 -keepclasseswithmembers class XXXX 保留类名和成员名。
如果添加好了混淆代码,那么要在build.gradle文件中再次配置下,打开混淆文件
buildTypes {
debug {
buildConfigField "boolean", "LOG_DEBUG", "true"
// VersionName后缀
versionNameSuffix "-debug"
minifyEnabled false
zipAlignEnabled false
shrinkResources false
}
release {
// 不显示log
buildConfigField "boolean", "LOG_DEBUG", "false"
// 混淆
minifyEnabled true
// Zipalign优化
zipAlignEnabled true
// 移除无用的resource
shrinkResources true
// 混淆配置
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
google默认混淆文件
位置
Sdk\tools\proguard
默认文件为
# This is a configuration file for ProGuard. # http://proguard.sourceforge.net/index.html#manual/usage.html # # This file is no longer maintained and is not used by new (2.2+) versions of the # Android plugin for Gradle. Instead, the Android plugin for Gradle generates the # default rules at build time and stores them in the build directory. -dontusemixedcaseclassnames -dontskipnonpubliclibraryclasses -verbose # Optimization is turned off by default. Dex does not like code run # through the ProGuard optimize and preverify steps (and performs some # of these optimizations on its own). -dontoptimize -dontpreverify # Note that if you want to enable optimization, you cannot just # include optimization flags in your own project configuration file; # instead you will need to point to the # "proguard-android-optimize.txt" file instead of this one from your # project.properties file. -keepattributes *Annotation* //使用注解需要添加 -keep public class com.google.vending.licensing.ILicensingService -keep public class com.android.vending.licensing.ILicensingService # For native methods, see http://proguard.sourceforge.net/manual/examples.html#native -keepclasseswithmembernames class * {//指定不混淆所有的JNI方法 native <methods>; } # keep setters in Views so that animations can still work. # see http://proguard.sourceforge.net/manual/examples.html#beans -keepclassmembers public class * extends android.view.View {//所有View的子类及其子类的get、set方法都不进行混淆 void set*(***); *** get*(); } # We want to keep methods in Activity that could be used in the XML attribute onClick -keepclassmembers class * extends android.app.Activity {//不混淆Activity中参数类型为View的所有方法 public void *(android.view.View); } # For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations -keepclassmembers enum * {//不混淆Enum类型的指定方法 public static **[] values(); public static ** valueOf(java.lang.String); } //不混淆Parcelable和它的子类,还有Creator成员变量 -keepclassmembers class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator CREATOR; } //不混淆R类里及其所有内部static类中的所有static变量字段 -keepclassmembers class **.R$* { public static <fields>; } # The support library contains references to newer platform versions. # Don't warn about those in case this app is linking against an older # platform version. We know about them, and they are safe. -dontwarn android.support.**//不提示兼容库的错误警告 # Understand the @Keep support annotation. -keep class android.support.annotation.Keep -keep @android.support.annotation.Keep class * {*;} -keepclasseswithmembers class * { @android.support.annotation.Keep <methods>; } -keepclasseswithmembers class * { @android.support.annotation.Keep <fields>; } -keepclasseswithmembers class * { @android.support.annotation.Keep <init>(...); }
- 代码中使用了反射,如一些ORM框架的使用
需要保证类名 方法不变, 不然混淆后, 就反射不了 - 使用GSON、fastjson等JSON解析框架所生成的对象类
生成的bean实体对象,内部大多是通过反射来生成, 不能混淆 - 引用了第三方开源框架或继承第三方SDK,如开源的okhttp网络访问框架,百度定位SDK等
在这些第三库的文档中 一班会给出 相应的 混淆规则, 复制过来即可 - 有用到WEBView的JS调用接口
没真么用过这块, 不是很熟, 网上那个看到的 - 继承了Serializable接口的类
在反序列画的时候, 需要正确的类名等, 在Android 中大多是实现 Parcelable来序列化的
- 代码中使用了反射,如一些ORM框架的使用
如果用到了反射需要加入
-keepattributes Signature
-keepattributes EnclosingMethod
如果想让一些bean 对象不混淆, 里 com.aaa.bean 包下面的全是 Json框架生成的bean对象, 那么只需加入:
-keep class aaa.**{*;}//不混淆所有的com.czy.bean包下的类和这些类的所有成员变量
继承了Serializable接口的类,需要加上
//不混淆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();
}
WEBView的JS调用接口
-keepclassmembers class fqcn.of.javascript.interface.for.webview {
public *;
}
-keep class com.xxx.xxx.** { *; }//保持WEB接口不被混淆 此处xxx.xxx是自己接口的包名
不混淆某个类
-keep class com.aaa.**//不混淆所有com.aaa包下的类,** 换成具体的类名则表示不混淆某个具体的类
不混淆某个类和成员变量
-keep class com.clock.**{*;}//不混淆所有com.clock包下的类和类中的所有成员变量,**可以换成具体类名,*可以换成具体的字段,可参照Serialzable的混淆
移除一些log代码:
移除Log类打印各个等级日志的代码,打正式包的时候可以做为禁log使用,这里可以作为禁止log打印的功能使用,另外的一种实现方案是通过BuildConfig.DEBUG的变量来控制
-assumenosideeffects class android.util.Log {
public static *** v(...);
public static *** i(...);
public static *** d(...);
public static *** w(...);
public static *** e(...);
}