天天看點

Android Progurad 代碼混淆

Android Progurad 代碼混淆

ref:

ProGuard基礎文法和打包配置.md

https://github.com/D-clock/Doc/blob/master/Android/Gradle/3_ProGuard%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95%E5%92%8C%E6%89%93%E5%8C%85%E9%85%8D%E7%BD%AE.md

AndroidStudio下ProGuard混淆打包

https://github.com/D-clock/Doc/blob/master/Android/Gradle/4_AndroidStudio%E4%B8%8BProGuard%E6%B7%B7%E6%B7%86%E6%89%93%E5%8C%85.md

proguard-rules.pro 模闆

https://github.com/AnyLifeZLB/AndroidAppFrameWork/blob/master/main/proguard-rules.pro

Proguard官方使用手冊:

https://stuff.mit.edu/afs/sipb/project/android/sdk/android-sdk-linux/tools/proguard/docs/index.html#manual/usage.html

代碼壓縮通過 ProGuard 提供,ProGuard 會檢測和移除封裝應用中未使用的類、字段、方法和屬性,包括自帶代碼庫中的未使用項(這使其成為以變通方式解決 64k 引用限制的有用工具)。ProGuard 還可優化位元組碼,移除未使用的代碼指令,以及用短名稱混淆其餘的類、字段和方法。混淆過的代碼可令您的 APK 難以被逆向工程,這在應用使用許可驗證等安全敏感性功能時特别有用。

要啟用資源壓縮,請在 ​

​build.gradle​

​ 檔案中将 ​

​shrinkResources​

​ 屬性設定為 ​

​true​

​(在用于代碼壓縮的 ​

​minifyEnabled​

​ 旁邊)。例如:

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

如果您尚未使用代碼壓縮用途的 ​

​minifyEnabled​

​ 建構應用,請先嘗試使用它,然後再啟用 ​

​shrinkResources​

​,因為您可能需要編輯 ​

​proguard-rules.pro​

​檔案以保留動态建立或調用的類或方法,然後再開始移除資源。

8. 混淆技巧

混淆能讓反編譯的代碼可讀性變的很差,而且還能顯著的減少APK包的大小。

1). 第一個技巧

相信很多朋友對混淆都覺得麻煩,甚至說,非常亂。因為添加混淆規則需要查詢官方說明文檔,甚至有的官方文檔還沒說明。當你引用了太多庫後,添加混淆規則将使一場噩夢。

這裡介紹一個技巧,不用查官方文檔,不用逐個庫考慮添加規則。

首先,除了預設的混淆配置(android-sdk/tools/proguard/proguard-android.txt), 自己的代碼肯定是要自己配置的:

## 位于module下的proguard-rules.pro
#####################################
######### 主程式不能混淆的代碼 #########
#####################################

-dontwarn xxx.model.**
-keep class xxx.model.** { *; }

## 等等,自己的代碼自己清楚

#####################################
########### 不優化泛型和反射 ##########
#####################################

-keepattributes Signature      

接下來是麻煩的第三方庫,一般來說,如果是極光推的話,它的包名是cn.jpush, 添加如下代碼即可:

-dontwarn cn.jpush.**
-keep class cn.jpush.** { *; }      

其他的第三庫也是如此,一個一個添加,太累!其實可以用第三方反編譯工具(比如jadx:​​https://github.com/skylot/jadx​​ ),打開apk後,一眼就能看到引用的所有第三方庫的包名,把所有不想混淆或者不确定能不能混淆的,直接都添加又有何不可:

#####################################
######### 第三方庫或者jar包 ###########
#####################################

-dontwarn cn.jpush.**
-keep class cn.jpush.** { *; }

-dontwarn com.squareup.**
-keep class com.squareup.** { *; }

-dontwarn com.octo.**
-keep class com.octo.** { *; }

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

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

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

-dontwarn u.aly.**
-keep class u.aly.** { *; }

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

-dontwarn com.baidu.**
-keep class com.baidu.** { *; }

-dontwarn com.facebook.**
-keep class com.facebook.** { *; }

-dontwarn com.google.**
-keep class com.google.** { *; }

## ... ...      

2). 第二個技巧

一般release版本混淆之後,像友盟這樣的統計系統如果有崩潰異常,會記錄如下:

java.lang.NullPointerException: java.lang.NullPointerException
    at com.xxx.TabMessageFragment$7.run(Unknown Source)      

這個Unknown Source是很要命的,排除錯誤無法定位到具體行了,大大降低調試效率。

當然,友盟支援上傳Mapping檔案,可幫助定位,mapping檔案的位置在:

project > module
        > build > outputs > {flavor name} > {build type} > mapping.txt      

如果版本一多,mapping.txt每次都要重新生成,還要上傳,終歸還是麻煩。

其實,在proguard-rules.pro中添加如下代碼即可:

-keepattributes SourceFile,LineNumberTable      

當然apk包會大那麼一點點(我這裡6M的包,大個200k吧),但是再也不用mapping.txt也能定位到行了,為了這種解脫,這個代價我個人覺得是值的,而且超值!