Android 簡化程式碼 (程式碼混淆)
阿新 • • 發佈:2019-01-30
前言:
為了使你的APK檔案儘可能小,你應該開啟簡化功能以除去在釋出版本中那些沒有使用過的程式碼和資源。這個章節將教你如何
在編譯期間決定什麼程式碼予以保留,什麼程式碼應該除去。
通過ProGuard,我們能夠將程式碼進行一個簡化操作。ProGuard簡化的原理主要是判斷在已打包的app或者庫檔案中,哪些類,
方法或者屬性沒有使用過,然後就將其予以移除。與此同時,ProGuard還可以優化位元組碼,移除沒有使用的程式碼指令,還可以
通過使用簡短命名的方式來實現對已保留的類,屬性和方法進行混淆的操作。這個已混淆的程式碼是很難再被逆向處理的,這是
很有意義的,尤其是當你的app對安全級別有較高要求時。
簡化程式碼
為了能夠通過ProGuard開啟程式碼簡化的功能,在build.gradle檔案對應的build type中需要將minifyEnabled置為true。 需要知道的是,在編譯期間,程式碼簡化操作是很長耗是的一件事,所以在除錯版本中去編譯時,你應該禁止掉這個程式碼簡化的操作。 與此同時,對於使用了程式碼簡化的APK檔案,對其去進行一個測試是非常重要的,因為有可能由於你沒有進行很好的保留程式碼定製的 操作,有可能會引發很多bug,所以這個測試很有必要。例如,在以下build.gradle的釋出版本這個片段中就使能了程式碼簡化的功能:android { buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile(‘proguard-android.txt'), 'proguard-rules.pro' } } ... }注意:在使用Instant Run的時候,在Android Studio的ProGuard是被禁止掉的 此外,
minifyEnabled
和proguardFiles
屬性,定義了Proguard的規則:
>getDefaultProguardFile(‘proguard-android.txt')方法從Android
SDK的tools/proguard/目錄下獲取到了一個預設的
ProGuard配置檔案
提示:對於更高級別的程式碼壓縮,你可以嘗試使用同一個目錄下的proguard-android-optimize.txt檔案。它包含了同樣的ProGuard
規則,但是它是通過在位元組碼中對其進行一個優化分析的操作,更大限度地減小APK的容量大小,以便APK可以執行得更快
>proguard-rules.pro
這個檔案內來定製一些包含ProGuard規則的操作。預設情況下,這個檔案位於module的根目錄
(與build.gradle這個檔案時緊挨在一起的)
若對於每個build variant(構建變體)也想指定一個ProGuard規則,你可以在相應的productFlavor塊中增加一個proguardFiles屬性。
例如,下邊就添加了一個flavor2-rules.pro檔案到flavor2中,現在,flavor2現在就有了三條ProGuard規則,因為在release塊中的
規則也是生效的。
android { ... buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } productFlavors { flavor1 { } flavor2 { proguardFile 'flavor2-rules.pro' } } }那麼,在每次編譯後,ProGuard將會生成如下檔案:
-
dump.txt
- 描述了在APK中,所有class檔案內在的一個結構
-
mapping.txt
- 描述了混淆之前和混淆之後,類,方法,屬性的一一對應關係
-
seeds.txt
- 列出了哪些類和成員沒有被混淆
-
usage.txt
- 列出了APK中哪些程式碼已被移除
這些輸出檔案都儲存在 <module-name>/build/outputs/mapping/release/
目錄下
決定哪些程式碼應該保留
在一些情況下,這個預設的ProGuard配置檔案(proguard-android.txt)就足夠了,ProGuard會將所有沒有使用的程式碼移除掉, 但也僅僅只限於沒有使用過的程式碼將會被移除。然後,在許多情況下,對於ProGuard來說,是很難去做一個正確地判斷的,有可能 它移除了那些app實際上需要的一些程式碼,程式碼移除出錯的情形有可能來自以下這些情況: > 當你的app引用了一個來自於AndroidManifest.xml
檔案中的類的時候
>
當你的app從JNI介面中去呼叫了一個方法的時候
>
當你的app在執行期間去操作程式碼的時候(比如反射)
測試你的app將會顯示一些由於不正確地移除程式碼造成的錯誤,但是你也應該通過檢視儲存在<module-name>/build/outputs/mapping/release/
目錄下的 usage.txt 這個輸出檔案,去看一下什麼程式碼已被移除
為了解決這個錯誤,就需要ProGuard配置檔案通過 -keep 保留某些程式碼,比如:
-keep publicclassMyClass當然,你也可以通過新增 @keep 註釋到你想要保留的程式碼中。新增 @keep 到一個類上,可以讓這整個類都保持原樣。新增 @keep 到方法或屬性上,可以讓這個方法或屬性以及它的保持完整。需要注意一點的就是:這個註釋只有在你使用了 Annotations Support Library 才會有效。 在使用 --keep 這個選項時,你需要有很多的選擇。更多關於定製你的配置檔案的資訊,可以參考 ProGuard Manual 。當你的程式碼做簡化的時候,