安卓程式碼混淆
Proguard是安卓提供的方便開發者對程式碼和apk進行保護和精簡的工具,可在SDK/tools資料夾下找到。
proguard的作用 :
1,程式碼混淆
2,精簡程式碼,刪掉沒有用到的程式碼,減小apk的體積。
使用場景:
1,對sighed APK進行程式碼混淆和精簡,從而使得釋出的程式碼可以防止被別人反編譯解析。(注意,直接build生成的APK是不進行混淆的,必須是signed的apk才會混淆)
2,對jar包進行混淆,方便將自己的程式碼(jar包)給別人使用並保證關鍵程式碼的不可見性。
下面分別針對以上兩種情況進行說明:
混淆APK:
所謂混淆APK,就是讓反編譯APK後得到的程式碼是混淆的。在Android Studio中,可以自動在打包APK的時候程式碼進行混淆。方法很簡單,只需要三步:
- 在app下的build.gradle中配置:
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
上面紅色的單詞由false改成true
- 在proguard-rules.pro中進行配置,即按照proguard的語法規則對自己工程中的程式碼進行選擇性的混淆。這裡給出一個典型的配置如下:
-optimizationpasses 5 #指定程式碼壓縮級別
-dontusemixedcaseclassnames #混淆時不會產生形形色色的類名
-dontskipnonpubliclibraryclasses #指定不忽略非公共類庫
-dontpreverify #不預校驗,如果需要預校驗,是-dontoptimize
-ignorewarnings #遮蔽警告
-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.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
-keep class android.support.v7.** { *; } #過濾android.support.v7 注意這裡v4還是v7要看gradle裡面compile了那個擴充套件包
-keep interface android.support.constraint.** { *; }
-keep class com.alibaba.fastjson.** {*;} #保持第三方包fastjson不被混淆,否則會報錯
以上程式碼中,藍色基本可以固定不變,綠色部分是為了讓引入的第三方包不混淆,如果不新增會報錯。比如不新增v7支援包則會導致Studio對整個V7包進行混淆 ,然後就發現它會混淆好久。。。至於對自己建立的包裡面那些類需要混淆哪些不混淆,讀者可以自己百度這方面的語法規則,數不勝數。
- 利用Studio中的build-signedAPK釋出簽名APK,完了以後在app下就會生成app-release.apk,這個就是我們得到的混淆程式碼後的apk。下圖就是反編譯APK以後得到的 jar包中的程式碼,已經被混淆。
混淆JAR包:
jar包的混淆方法我之前試過在Studio中進行,結果愣是沒搞定,然後我就採用的proguard自帶的GUI介面實現了jar包混淆,方法為:
在安卓SDK下找到\tools\proguard\bin資料夾,開啟proguardgui.bat(linux下為.sh),出現一個介面,這裡其實挺簡單,首先按照上面說的proguard-rules.pro裡面的規則寫一個配置檔案,字尾是.txt,然後載入,直接跳到最後一步process即可,這裡需要注意的是,配置檔案裡面跟之前不太一樣,主要有兩點區別:
1,因為是對jar包混淆,所以需要寫上injar和outjar的名字,比如我寫的:
-injars android.jar
-outjars 'confuseDemo.jar'
其中android.jar是需要混淆的jar包(放到proguardgui.bat同個目錄下),後者為混淆後的 jar包,會自動在該目錄下生成。
2,被混淆的jar包不包含裡面引用到的第三方庫,需要在配置檔案裡面宣告它用到的第三方jar包,比如我寫的:
-libraryjars C:\Users\Machenike-Pc\Desktop\fastjson.jar
-libraryjars C:\Users\Machenike-Pc\Desktop\org.apache.http.legacy.jar
-libraryjars E:\softneed\Andriod\AndroidSDK\platforms\android-21\android.jar
需要注意最後一行,因為安卓工程肯定要用安卓SDK,因此要加上對應版本的sdk中的jar包
其他的寫法跟之前的proguard-rules.pro相同。
最後總結一下:在混淆過程中,如果工程比較大,一次混淆很可能會出現各種問題,這裡就需要有耐心逐個排除。在較大的工程中引用的jar包可能會有數十個,各個jar包在官網或使用說明裡可能會有說明如何在混淆中使用。如果沒有,最好是將整個jar包都不要混淆,即加上規則: -keep class xx.xxx.xxxx.** {*;} ,該方法可以將jar包裡面的所有類和子包裡面的類都排除不混淆,就不會出現問題。 此外即使所有的包都不混淆,也有報錯的可能,主要有兩個原因:
1.沒有按照規則把系統元件,資源類,列舉等排除,比如我在專案中就忘記了將實現Parcelable介面的類排除,結果導致伺服器傳來的資料無法獲取,app執行時沒有正常顯示資料。
2.有的jar包中使用了反射技術,此時在呼叫時就會出現及時jar包沒有混淆,但是如果呼叫的類混淆了,也會產生錯誤。這種情況下需要通過看log日誌,定位到出錯的類,將該類混淆去掉。