第2部分:縮小程式碼
在本章中,您將找到適用於幾乎所有應用程式的建議。這一切都是為了保持程式碼庫的清潔,檢查依賴關係,併為您提供幫助完成這些任務的工具。
Dex程式碼縮小
您要做的第一件事是啟用內建縮小器。它將嘗試剝離任何未使用的類和類成員,以及使用較短的名稱重新命名任何識別符號。這兩個操作都會使得到的程式碼變小,但後者會使除錯變得很麻煩,所以我建議你只為你的 釋出 構建型別啟用縮小:
的build.gradle
android { ... buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro' } } }
第二行為ProGuard規則格式的minifier提供配置檔案。第一個配置檔案( Sdk / tools / proguard / proguard-android.txt )包含在SDK中,幷包含每個Android專案的一些理智預設值。檢視這些規則可以幫助您熟悉Proguard配置語法。例如,這可以保留(換句話說,防止被刪除或重新命名)View子類中的任何setter或getter方法:
#在檢視中保留setter,這樣動畫仍然可以工作。 -keepclassmembers public class * extends android.view.View { void set *(***); ***得*(); }
運氣好的話,您的應用程式將使用預設配置。在構建過程中,名為AAPT的工具還會生成必要的規則,以保留Manifest中提到的所有活動和其他元件,以及XML佈局中使用的任何檢視。庫依賴項應通過消費者ProGuard檔案提供其minifier配置,但有時它們僅在其網站或手冊上提供必要的ProGuard規則。在這種情況下,您需要將它們複製到 app / proguard-rules.pro 檔案中。
遺憾的是,在啟用縮小功能後,您的應用程式將無法在執行時編譯或中斷,通常是通過為minifier刪除的類丟擲 ClassNotFoundException 。要解決此問題,您需要在 app / 資料夾中建立一個 proguard-rules.pro 檔案,並提供擺脫編譯時警告所需的規則(檢視訊息日誌以獲取資訊)。您還必須確保保留在執行時使用的任何類和成員,但是被minifier剝離。這些通常是程式碼的一部分,可以通過反射訪問。
一個特定情況是XML佈局中的自定義屬性將類名稱作為String,例如設定 RecyclerView 的 layoutManager :
<android.support.v7.widget.RecyclerView app:layoutManager =“android.support.v7.widget.GridLayoutManager” ... />
在這種情況下,AAPT將無法確定類的使用情況並生成必要的ProGuard規則。要應用修復,您應該在ProGuard配置中新增以下行,以防止 GridLayoutManager 類及其任何公共和受保護方法被刪除或重新命名:
-keep public class android.support.v7.widget.GridLayoutManager { public protected *; }
要檢查您編寫的配置規則是否具有所需的效果,可以使用ClassyShark等工具檢查生成的APK中的 classes.dex 檔案。 徹底測試您的應用程式 也很重要!應用程式開啟而不崩潰的事實並不表示正確的minifier配置。您 必須 測試應用中的每個螢幕和使用者流是否崩潰。(我可以建議檢視 Android測試支援庫和Espresso 嗎?:)
將ProGuard對映上載到Play
分析在使用者裝置上執行的混淆程式碼引發的異常,直到最近才有點不方便。通常,您必須從Play Developer Console複製堆疊跟蹤,並使用計算機上的工具以及在編譯時生成的ProGuard對映檔案來解碼原始類和方法名稱。

image.png
Play Developer Console現在可以選擇將對映檔案與APK一起上傳,並在Crashes和ANRs面板中顯示反混淆堆疊跟蹤。請記住,您使用的對映檔案必須來自與發行版APK完全相同的編譯執行。
注意:您將在此路徑下的專案資料夾中找到mappings.txt檔案:<module> /build/outputs/mapping/mapping.txt
圖書館的ProGuard配置
如果要構建要在其他需要ProGuard規則的專案中使用的AAR庫,則應使用 consumerProguardFiles 選項將ProGuard配置檔案與AAR打包在一起。這樣,使用您的庫的任何人都不必擔心在啟用縮放器時手動新增規則。在手冊中使用庫編譯專案時,還要確保提供有關任何其他要求的資訊。
的build.gradle
android { ... defaultConfig { consumerProguardFiles“proguard-rules.txt” } }
對Google Play服務使用粒度依賴關係

image.png
在專案中使用Google Play Services庫時,請記住切換到粒度依賴項。這意味著如果您只是使用廣告,地圖或GCM等幾項功能,那麼您將無法進入整個客戶端庫。您可以在 developers.google.com上 使用包含所有Gradle依賴關係字串的表格。順便說一句,ProGuard消費者規則包含在Play服務中,因此如果您為構建啟用程式碼縮減器,它們應該可以正常工作。
追蹤依賴關係
開發Android的好處是,如果你有問題,可能有人已經解決了它。隨著專案的增長,您通常會引入越來越多的外部依賴項來加速開發時間。最常見的可能是用於向後相容的Android支援庫,Play服務,影象載入庫,HTTP客戶端和各種其他SDK ......
開發人員經常問我:我應該使用哪個影象庫?我的專案有多少依賴項太多了?這些問題沒有確切的答案。如果你真的需要使用一個庫,因為它解決了你的問題(並且你理解了它的缺點),那就去吧。擁有合適的工具來幫助您確定它對專案規模的影響是非常重要的,這樣您就可以做出明智的決定。
傳遞庫依賴項
當你認為你只是“只是”新增一個小幫助庫時,突然你的Dex大小爆炸並且你的方法計數 遍及 屋頂,這可能是因為你通常在 build.gradle 檔案 中看 不到的傳遞依賴。幸運的是,有一些工具可以幫助:
$ ./gradlew app:依賴項 ... compile- 用於編譯主要源的類路徑。 +--com.android.support:appcompat-v7:23.1.1 | \--com.android.support:support-v4:23.1.1 | \--com.android.support:support-annotations:23.1.1 +--com.android.support:cardview-v7:23.1.1 +-com.android.support:design:23.1.1 | +--com.android.support:appcompat-v7:23.1.1(*) | +--com.android.support:recyclerview-v7:23.1.1 | | +--com.android.support:support-annotations:23.1.1 | | \--com.android.support:support-v4:23.1.1(*) | \--com.android.support:support-v4:23.1.1(*)+ -com.android.support:recyclerview-v7:23.1.1(*) \-com.android.support.test.espresso :咖啡怠速資源:2.2.1
該 <模組名>:依賴 命令給你的每個庫在您的專案和它的依賴關係樹的概述。版本號旁邊的星號(*)告訴您之前在輸出中已經提到了這個特定的依賴關係,因此無論如何它都會包含在您的專案中,除非您刪除它的所有其他例項。
注意:如果您使用的是產品風格,並且您只需要一個庫用於應用程式的某些變體(例如,僅適用於免費版本的廣告SDK),您可以指定以您的風味名稱為字首的
依賴項,例如 依賴項{freeCompile'...' }。
使用ClassyShark檢查Dex檔案
有時,為了保護開發人員免受版本衝突的影響,庫會直接在其程式碼中包含其依賴項,但包含更改的包名稱,基本上會隱藏原始版本。這也意味著您不會在Gradle依賴關係樹中看到這種依賴關係。
如果您希望更好地檢視APK中打包的確切類和包名稱,可以使用 ClassyShark 檢查您的Dex檔案。它也非常適合測試您的ProGuard規則,以確切瞭解它們對最終APK的影響。

image.png
注意:作為獎勵,ClassyShark將顯示包裹的方法計數,這可能有助於您識別最大的多指數違規者。

image

image