混淆作用

将程序变得难以阅读,防范程序被逆向。

Android Studio开启混淆的方法

Android Studio自身集成Java语言的ProGuard作为压缩,优化和混淆工具,可以配合Gradle构建工具使用。找到gradle里的minifyEnabled设置为true即可。

android {
...
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

以上示例代码表示对release版本混淆。

ProGuard作用

压缩 (Shrinking)

默认开启,以减少应用体积,移除未被使用的类和成员,并且会在优化动作执行之后再执行(因为优化后可能会再次暴露一些未被使用的类和成员)

-dontshrink 关闭压缩

优化(Optimization)

默认开启,在字节码级别执行优化,让应用运行的更快。

-dontoptimize  关闭优化
-optimizationpasses n 表示proguard对代码进行迭代优化的次数,Android一般为5

混淆(Obfuscation)

默认开启,增大反编译难度,类和类成员会被随机命名,除非用keep保护

dontobfuscate 关闭混淆

混淆后默认会在工程目录
app/build/outputs/mapping/release下生成一个mapping.txt文件,这就是混淆规则,我们可以根据这个文件把混淆后的代码反推回源本的代码,所以这个文件非常重要。
有时候混淆后会报错,可能要对部分避免混淆。

(1)

-keep class cn.hadcn.test.**
-keep class cn.hadcn.test.*

其中一颗星表示只保持该包下的类名
两颗星表示把本包和所含子包下的类名都保持。

(2)

-optimizationpasses 5                                                           # 指定代码的压缩级别
-dontusemixedcaseclassnames # 是否使用大小写混合
-dontskipnonpubliclibraryclasses # 是否混淆第三方jar
-dontpreverify # 混淆时是否做预校验
-verbose # 混淆时是否记录日志
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* # 混淆时所采用的算法

-keep public class * extends android.app.Activity # 保持哪些类不被混淆
-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.app.backup.BackupAgentHelper # 保持哪些类不被混淆
-keep public class * extends android.preference.Preference # 保持哪些类不被混淆
-keep public class com.android.vending.licensing.ILicensingService # 保持哪些类不被混淆

-keepclasseswithmembernames class * { # 保持 native 方法不被混淆
native <methods>;
}

-keepclasseswithmembers class * { # 保持自定义控件类不被混淆
public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int); # 保持自定义控件类不被混淆
}

-keepclassmembers class * extends android.app.Activity { # 保持自定义控件类不被混淆
public void *(android.view.View);
}

-keepclassmembers enum * { # 保持枚举 enum 类不被混淆
public static **[] values();
public static ** valueOf(java.lang.String);
}

-keep class * implements android.os.Parcelable { # 保持 Parcelable 不被混淆
public static final android.os.Parcelable$Creator *;
}

-keep class MyClass; # 保持自己定义的类不被混淆

guillep PullToRefresh

-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

-keep public class * extends android.app.Activity
-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.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService

-keepclasseswithmembernames class * {
native <methods>;
}

-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}

-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}

-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}</init></init></methods>

当在新版本的ADT创建项目时,混码的文件不再是proguard.cfg,而是project.properties和proguard-project.txt
如果需要对项目进行全局混码,只需要进行一步操作:

将project.properties的中 “#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt”的“#”去掉就可以了。

proguard-project.txt示例

#工程中含有第三方jar包
-libraryjars libs/android-support-v4.jar
-libraryjars libs/BaiduLBS_Android.jar

#项目里面包含的包也不能混淆
-keep class com.baidu.** {*;}
-dontwarn com.baidu.**

-keep class vi.com.gdi.bgl.android.java.** {*;}
-dontwarn vi.com.gdi.bgl.android.java.**

-keep class android.** {*;}
-dontwarn android.**

其它代码混淆工具:

APKProtect,将流程代码也乱序混淆,对抗反编译工具、反ida动态调试、反模拟器、校验dex文件等功能。


一些问题处理:

Note: duplicate definition of library class [org.apache.http.conn.scheme.HostNameResolver]
Note: duplicate definition of library class [org.apache.http.conn.scheme.SocketFactory]
Note: duplicate definition of library class [org.apache.http.conn.ConnectTimeoutException]
Note: duplicate definition of library class [org.apache.http.params.HttpParams]
Note: duplicate definition of library class [android.net.http.SslCertificate$DName]
Note: duplicate definition of library class [android.net.http.SslError]
Note: duplicate definition of library class [android.net.http.SslCertificate]

在proguard-rules.pro添加

-printconfiguration config.txt

会看到生成的config.txt有:

-libraryjars 'D:\tools\android\platforms\android-23\android.jar'

-libraryjars 'D:\tools\android\platforms\android-23\optional\org.apache.http.legacy.jar'

那几个提示重复的class在 org.apache.http.legacy.jar和android.jar中重复定义。 目前处理方法只有使用:

-dontnote android.net.http.*
-dontnote org.apache.commons.codec.**
-dontnote org.apache.http.**