縮減程式碼和資源(Shrink Your Code and Resources)
一、程式碼縮減和資源縮減概述
為儘可能縮減apk包的大小,我們應該在release版本中移除未使用的程式碼和資源。這篇文件描述如何在構建過程中指定保留和移除的程式碼與資源。 程式碼縮減(Code shrinking)利用ProGuard ,它可以檢測和移除app中沒有使用的類、欄位、方法和屬性,包括來自程式碼庫的那些。ProGuard還可以優化class檔案,刪除未使用的程式碼指令,並使用短名稱來混淆類欄位和方法。 資源縮減(Resource shrinking)可利用Gradle配置,它可以移除app中未使用的資源,包括程式碼庫中未使用的資源。它與程式碼縮減一起工作,使得一旦未使用的程式碼被移除,任何不再被引用的資源也可以被安全地移除。 本文件中的功能依賴於:
- SDK Tools25.0.10 or higher
- Android Plugin for Gradle2.0.0 or higher
二、程式碼縮減(Shrink Your Code)
1.啟用程式碼縮減
要使用ProGuard啟用程式碼縮減,請將minifyEnabled true新增到build.gradle檔案中的相應build type。 注意,程式碼縮減會減慢構建時間,因此,儘量避免在dbeug版本上使用它。不過重要的是,必須在在啟用程式碼縮減的apk上進行測試,因為如果沒有足夠自定義要保留的程式碼,它可能會引入錯誤。 程式碼縮減gradle配置示例:
android {
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile(‘proguard-android.txt'),
'proguard-rules.pro'
}
}
}
除了指定minifyEnabled屬性,proguardFiles屬性還定義了ProGuard規則:
- getDefaultProguardFile('proguard-android.txt')從SDK tools /proguard /下的proguard-android.txt設定預設的ProGuard設定。
(備註:為更好地程式碼縮減,可以利用位於相同位置的proguard-android-optimize.txt檔案。 它包括相同的ProGuard規則,但在執行分析位元組碼級別等方面進一步優化,可以更好地減少apk大小,並幫助它執行更快。) - proguard-rules.pro中可以新增自定義ProGuard規則。預設情況下,此檔案位於module的根目錄(在build.gradle檔案旁邊)。
我們也可以為不同的Variant指定不同的ProGuard規則:
android {
...
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
}
productFlavors {
flavor1 {
}
flavor2 {
proguardFile 'flavor2-rules.pro'
}
}
}
專案構建後,在/build/outputs/mapping/release/下會生成幾個檔案:
- dump.txt:apk檔案中所有類檔案間的內部結構
- mapping.txt:混淆前後程式碼間的對映
- seeds.txt:未被混淆的類和成員
- usage.txt:未使用的、被apk刪除的程式碼
2.定義保留哪些程式碼
大多數情況下,預設的ProGuard配置檔案(proguard-android.txt)就足夠了,ProGuard刪除所有未使用的程式碼。然而,有些情況下,ProGuard很難正確分析,它可能會刪除您的應用程式實際需要的程式碼。比如:
- 當僅在AndroidManifest.xml檔案中引用的類
- 當從JNI呼叫方法時
- 當在位元組碼中操作程式碼時(如使用反射)
為修復錯誤並強制ProGuard保留某些程式碼,需要在ProGuard配置檔案中新增一個-keep標記,比如:-keep public class MyClass
或者,您可以將@Keep註釋新增到要保留的程式碼。請注意,此註釋僅在使用註釋支援庫時可用。
使用-keep選項時,您應該考慮許多因素;有關自定義配置檔案的更多資訊,請閱讀 ProGuard手冊。
3.解析混淆後的堆疊跟蹤(Stack trace)
ProGuard縮減程式碼後,讀取堆疊跟蹤是很困難的,因為方法名都被混淆處理了。幸運的是,ProGuard在構建過程中建立了mapping.txt作為混淆前後程式碼的對映。
由於mapping.txt在每次構建過程中會被重寫,所以需要在每個版本對應的mapping.txt儲存到對應的目錄下。如果使用者從舊版本app提交混淆的堆疊跟蹤,我們就可以通過每個版本對應的mapping.txt,來除錯問題。
當我們在應用商店釋出app時,也可以將對應的mapping.txt提交上去,這樣應用商店就可以將使用者報告的問題中直接進行解析。
要將混淆的堆疊跟蹤轉換為可讀的堆疊跟蹤,請使用回溯指令碼(Windows上為retrace.bat;Mac上為retrace.sh)。 它位於 / tools / proguard /目錄中。該指令碼採用mapping.txt檔案和堆疊跟蹤,產生一個新的、可讀的堆疊跟蹤。
使用retrace.bat的語法:
retrace.bat|retrace.sh [-verbose] mapping.txt []
例如:
retrace.bat -verbose mapping.txt obfuscated_trace.txt
三、資源縮減(Shrink Your Resources)
1.啟用資源縮減
資源縮減必須與程式碼縮減相結合。程式碼縮減移除所有未使用的程式碼後,資源縮減器可以識別應用程式仍在使用哪些資源。 未被使用的資源,將會被資源縮減器移除。
為使用資源縮減,需要在gradle檔案中設定shrinkResources屬性,例如:
android {
...
buildTypes {
release {
shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
}
}
注意,資源縮減不會移除value檔案下的資源(比如strings, dimensions, styles, and colors),aapt不允許gradle這樣做。
2.指定保留哪些資源
對於一些你希望保留或移除的資源,可以建立一個xml檔案,以resource為標籤,通過tools:keep和tools:discard指定要保留和要移除的資源,多個資源之間以逗號分隔。例如:
tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"
tools:discard="@layout/unused2" />
將此檔案儲存在專案資源中,比如res/raw/keep.xml,構建時不會將該檔案打包到apk中。
指定要移除的資源,比起來直接刪除掉,似乎有些傻。但是,對於構建多個Variant,卻是很有用的。我們可以為不同的變體指定不同的keep.xml。
3.啟用嚴格引用檢查
通常,資源縮減器能夠判斷出指定資源是否被使用。但是,如果你的程式碼呼叫了Resources.getIdentifier()(或者你的庫中的任何一個,比如AppCompat庫),這意味著你的程式碼是基於動態生成的字串查詢資源名稱。這樣操作時,資源縮小器預設情況下會防禦性地執行,並將匹配名稱格式的所有資源標記為可能已使用而不會去移除。
例如,以下程式碼會將所有帶有img_字首的資源標記為已使用。
String name = String.format("img_%1d", angle + 1);
res = getResources().getIdentifier(name, "drawable", getPackageName());
資源縮小器還檢視程式碼中的所有字串常量以及各種res / raw /資源,以類似於file:///android_res/drawable//ic_plus_anim_016.png的格式查詢資源url。如果它發現類似這樣的字串或其他,也不會移除它們。
這些是預設情況下啟用的安全縮減模式的示例。但是,當不關注#“better safe than sorry”#時,可以指定資源縮減器僅保留其確定使用的資源。為此,請在keep.xml檔案中將shrinkMode設定為strict,如下所示:
tools:shrinkMode="strict" />
如果您啟用了嚴格縮減模式,並且您的程式碼還引用了具有動態生成的字串的資源,那麼您必須使通過tools:keep手動保留這些資源。
4.移除帶有選擇性的資源
資源縮減器只會移除沒有在程式碼中被引用的資源,這也意味著,它不會移除那些為不同裝置配置的帶有選擇性質的資源。必要的情況下,可以利用resConfigs屬性移除這些資源。
例如,如果您使用的庫包含語言資源,則apk會包含這些庫中的所有翻譯語言字串。如果您只想保留指定的語言,可以使用resConfig屬性進行指定,並將刪除未指定語言的任何資源。
以下程式碼段顯示瞭如何將語言資源僅限英語和法語:
android {
defaultConfig {
... ...
resConfigs“en”,“fr”
}
}
同樣,您可以自定義要在apk中包含哪些螢幕密度或ABI資源,併為不同裝置構建不同的apk。
5.合併重複的資源
這裡的合併英文為merge,帶有解決衝突的意思。
預設情況下,gradle會合並相同名稱的資源,例如可能在不同資原始檔夾中具有相同名稱的drawable。 此行為不受shrinkResources屬性控制,不能禁用,因為必須避免在多個資源與程式碼查詢的名稱匹配時出現錯誤。
僅當兩個或多個檔案共享相同的資源名稱時,才會進行資源合併。gradle選擇哪個檔案被認為是重複項中的最佳選擇(基於下面描述的優先順序順序),並且僅將那個資源傳遞給aapt以在apk中分發。
gradle在以下位置查詢重複的資源:
- main resources,與主源集相關,一般位於src / main / res /。
- 變體覆蓋,從the build type和build flavors。
- 庫專案依賴項。
gradle在以下優先順序順序中合併重複資源:Dependencies→Main→Build flavor→Build type
例如,如果重複資源出現在main resources和build flavor,gradle會選擇build flavor中的。
6.資源合併描述檔案
當縮減資源時,Gradle Console會顯示從應用程式包中刪除的資源的摘要。例如:
:android:shrinkDebugResources
Removed unused resources: Binary resource data reduced from 2570KB to 1711KB: Removed 33%
:android:validateDebugSigning
gradle還會在/build/outputs/mapping/release/建立一個檔案resources.txt,來描述哪些資源被引用和被移除。
作者:抹香君
連結:http://www.jianshu.com/p/46560895b42c
來源:簡書
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。
相關文章
- 效能優化 (十一) ProGuard 對程式碼和資源壓縮優化
- Oracle 10g Shrink Table - Shrink Space 收縮空間Oracle 10g
- 表空間(資料檔案shrink)收縮示例
- [zt] 收縮使用者資料庫 (shrink database)資料庫Database
- shrink收縮檔案空間
- SQL Server如何截斷(Truncate)和收縮(Shrink)事務日誌SQLServer
- 縮減apk大小APK
- Android資源知識(一)之Resources概覽Android
- 程式碼縮寫和長度值
- 程式碼的縮排和巢狀巢狀
- 關於SQL 2008資料庫壓縮後收縮(database shrink)的測試實驗和效能比較SQL資料庫Database
- Effective Java -- 使用try-with-resources優化程式碼Java優化
- HikariPool原始碼(三)資源池動態伸縮原始碼
- CodeRunner啟用碼破解資源4.3
- 【SHRINK】Oracle收縮表的詳細命令參考Oracle
- 縮小日誌大小,截斷日誌;然後shrink
- linux 縮減LV大小Linux
- k8s的api-resources資源型別介紹K8SAPI型別
- system-design-resources: 最好的系統設計英文資源
- Steven Code Review 程式碼線上審查工具[開源]View
- booster分析-App資源壓縮APP
- 格式化和壓縮css樣式程式碼CSS
- 盒型程式碼縮寫及單位和值
- 利用ADO壓縮Access資料庫程式碼資料庫
- jquery實現的下拉和收縮程式碼例項jQuery
- 如何減小微信小程式程式碼包大小微信小程式
- PolyCoder:號稱超過Codex的開源AI程式碼生成器AI
- 合成資料: 利用開源技術節約資金、時間和減少碳排放
- 使用Egret外掛壓縮程式碼包體積,減少請求數量的實戰教程
- 使用MVVM減少控制器程式碼實戰(減少56%)MVVM
- ALTER TABLE MOVE和SHRINK SPACE區別
- JStorm Found multiple defaults.yaml resources. You're probably bundling the Storm jars with your topJSORMYAMLJAR
- 開源無程式碼 / 低程式碼平臺 NocoBase 0.20:支援多資料來源
- Java語法糖: 使用 try-with-resources 語句安全地釋放資源Java
- oracle shrinkOracle
- 歡迎使用開源的程式碼生成器Code-BuilderUI
- BigCode:使用AI自動生成程式碼的開源工具GCAI開源工具
- 程式碼整潔之道之做減法