ProGuard
是一個(gè)免費(fèi)的Java
類文件縮小,優(yōu)化,混淆和預(yù)驗(yàn)證的工具。它檢測(cè)和刪除未使用的類,字段,方法和屬性;優(yōu)化字節(jié)碼并刪除未使用的指令;它使用短的無意義的名稱重命名剩余的類,字段和方法。所得到的應(yīng)用程序和庫更小,更快,并且更好地針對(duì)逆向工程進(jìn)行優(yōu)化。
一、混淆的四個(gè)功能
- 壓縮:移除無效的類、屬性、方法等;
- 優(yōu)化:優(yōu)化字節(jié)碼,并刪除未使用的結(jié)構(gòu);
- 混淆:類名、屬性名、方法名混淆成難度字母;
- 預(yù)效驗(yàn)
minifyEnabled
改為true
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
二、不能參與混淆的
-
AndroidManifest
中配置的類,比如四大組件和Application
類。 -
Fragment
不參與混淆app包下和v4包下的分別keep下 - 所有實(shí)現(xiàn)了
Serializable
接口的類成員 - JNI調(diào)用的方法
- 反射用到的類
- 枚舉
- 項(xiàng)目中暴露的
JS
接口類及其調(diào)用的方法的聲明也不能混淆; - Layout文件引用到的自定義View
- 注解的類或參數(shù)或函數(shù)不能參與混淆
- 一些引入的第三方庫(一般都會(huì)有混淆說明的)
三、AAR對(duì)外提供的接口的處理
把a(bǔ)ar對(duì)外提供的接口,統(tǒng)一到一個(gè)類中,在混淆文件中加上keep方法,讓這個(gè)類不被混淆,同時(shí)R文件也能混淆
例如
-dontwarn okhttp3.**
-keep class okhttp3.**{*;}
四、混淆的文件示例
以下代碼的因包名而變化
#混淆的初始化配置##############################################
-ignorewarnings # 忽略警告,避免打包時(shí)某些警告出現(xiàn)
-optimizationpasses 5 # 指定代碼的壓縮級(jí)別
-dontusemixedcaseclassnames # 是否使用大小寫混合
-dontskipnonpubliclibraryclasses # 是否混淆第三方j(luò)ar
-dontpreverify # 混淆時(shí)是否做預(yù)校驗(yàn)
-verbose # 混淆時(shí)是否記錄日志
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* # 混淆時(shí)所采用的算法
####################################################################################################
## 1.四大組件和Application類不參與混淆
-keep public class * extends android.app.Activity
-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.Application
## 2.Fragment不需要在AndroidManifest.xml中注冊(cè),需要額外保護(hù)下
-keep public class * extends android.support.v4.app.Fragment
-keep public class * extends android.app.Fragment
-keep public class * extends android.support.v4.app.FragmentActivity
## 3.保持所有實(shí)現(xiàn) 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();
}
## 6.枚舉不被混淆
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
## 7.MyJavaInterface不能混淆,其調(diào)用的方法聲明也不能混淆,所以還要添加如下混淆
-keepclassmembers class com.example.administrator.webviewpagescannerapp.other.MJavascriptInterface{
public *;
}
-keepattributes *JavascriptInterface*
// 注解不參與混淆
-keepattributes *Annotation*
## 8.Layout文件引用到的自定義View
-keep public class * extends android.view.View {
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
public void set*(...);
}
##########################實(shí)體類不參與混淆############################
-keep class ai.botbrain.ttcloud.sdk.entity.** { *; }
######################對(duì)外提供的接口類不參與混淆################################
-keep class ai.botbrain.ttcloud.api.** { *; }
####################################################################################################
-dontwarn android.support.**
五、混淆時(shí)候遇到的ERROR
混淆遇到的錯(cuò)誤
Warning: there were 3 instances of library classes depending on program classes.
You must avoid such dependencies, since the program classes will
be processed, while the library classes will remain unchanged.
(http://proguard.sourceforge.net/manual/troubleshooting.html#dependency)
解決
-ignorewarnings
六、混淆的gradle配置
默認(rèn)情況下,Android Plugin會(huì)自動(dòng)給項(xiàng)目設(shè)置同時(shí)構(gòu)建應(yīng)用的debug
和release
版本。兩個(gè)版本之間不同主要圍繞著能否在一個(gè)安全設(shè)備上調(diào)試,以及APK
如何簽名。
所以當(dāng)想在debug
時(shí)候關(guān)閉混淆功能時(shí),同時(shí)把release
和debug
下的minifyEnabled
置為false
。
release {
// 是否混淆
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
七、給別人提供混淆的AAR注意事項(xiàng)
需求:把項(xiàng)目中的某一個(gè)模塊,打包成一個(gè)混淆的aar,集成到其他的項(xiàng)目中,同時(shí)暴露的接口不混淆,這個(gè)aar的依賴庫跟其他項(xiàng)目的依賴庫不能沖突。
模塊中引入的jar
在以下情況下是混淆不成功的:
1.假設(shè)有兩個(gè)模塊,moduleA
和moduleB
moduleA
依賴moduleB
moduleB
中引入了第三方的jar
,混淆的配置是在moduleA
中,這種情況下,moduleB
中的jar
是不被混淆的。
2.引入的jar
包是以網(wǎng)絡(luò)庫方式的依賴,是不被混淆的。
知道了以上注意點(diǎn),可以更好的為別人提供混淆后的aar,并減小類的沖突。