最近和一個(gè)iOS同學(xué)說(shuō),我們Android apk build要比ios慢很多,他問(wèn)我為什么要這么久,把我問(wèn)懵了,不知道怎么解釋。其實(shí)很多時(shí)候,你只要比別人多想一步就很厲害了。多問(wèn)問(wèn)自己為什么。
我們先看一張官方文檔提供的apk構(gòu)建流程圖

從上圖可以看出來(lái),構(gòu)建的過(guò)程主要分為兩步:
- 編譯源碼、資源以及第三方依賴庫(kù)
- 簽名、打包,生成apk
下面再來(lái)看另外一張圖,詳細(xì)分析了apk的構(gòu)建過(guò)程以及構(gòu)建過(guò)程中的工具

流程概述:
- 打包資源文件,生成R.java文件
- 處理aidl文件,生成對(duì)應(yīng)的java文件
- 編譯工程源文件,生成相應(yīng)的class文件
- 轉(zhuǎn)換剛剛生成的class文件以及第三方依賴的class文件,生成dex文件
- 打包生成apk
- 對(duì)apk進(jìn)行簽名,生成簽名之后的apk
- 對(duì)生成的apk進(jìn)行優(yōu)化,生成簽名+優(yōu)化后的apk
打包過(guò)程中需要的工具
aapt
Android資源打包工具,
目錄:${ANDROID_SDK_HOME} /build-tools/ANDROID_VERSION/aapt
aidl
將aidl文件轉(zhuǎn)成java文件
目錄:${ANDROID_SDK_HOME}/build-tools/ ANDROID_VERSION/aidl
javac
不用解釋了吧
目錄:${JDK_HOME}
dex
將class文件轉(zhuǎn)成Dalvik虛擬機(jī)能識(shí)別的dex文件
目錄:${ANDROID_SDK_HOME}/build-tools/ ANDROID_VERSION/dx
apkbuilder
打包生成apk
這里需要注意下,就是這個(gè)工具已經(jīng)在2014年就已經(jīng)被移除了,在sdk的build-tools目錄下根本就么有這個(gè)命令?,F(xiàn)在打包生成apk用的是${ANDROID_SDK_HOME}/tools/lib/sdk-xxx.jar中的ApkBuilderMain類。
Jarsigner
簽名工具,目錄在${JDK_HOME}
zipaling
對(duì)apk進(jìn)行優(yōu)化減少其在設(shè)備上運(yùn)行時(shí)的內(nèi)存占用。
目錄:${ANDROID_SDK_HOME}/build-tools/ ANDROID_VERSION/zipalign
構(gòu)建流程詳細(xì)分析
打包資源文件,生成R.java文件
這一步主要用的是aapt工具,打包的資源文件主要分為三部分,
- res目錄,包括圖片、xml等
- AndroidManifest.xml
- Assets文件
- Android.jar
上面這些資源文件中的xml(除了assets和raw目錄)基本都會(huì)被編譯成二進(jìn)制的xml文件,這樣空間更小。
經(jīng)過(guò)aapt之后,主要生成兩個(gè)文件,R.java文件以及resources.arsc文件。
R.java主要存放的是資源id,在我們公司的組件化過(guò)程中,為了防止插件和主站之間的資源id沖突,就是通過(guò)修改aapt源碼來(lái)生成不同id,確保資源id不會(huì)沖突。
resources.arsc,存放了資源id與路徑之間的映射關(guān)系。
關(guān)于資源打包的詳細(xì)過(guò)程,可以參考老羅的博客https://blog.csdn.net/luoshengyang/article/details/8744683
這里插播一條res/raw和assets目錄的區(qū)別
- 兩個(gè)目錄下的資源都直接拷貝到apk包中,不會(huì)編譯成二級(jí)制文件
- raw目錄下的文件會(huì)被映射到R.java文件中,可以通過(guò)R.id.xx來(lái)訪問(wèn),而assets目錄文件只能通過(guò)AssetManager來(lái)訪問(wèn)
- assets目錄下可以創(chuàng)建目錄,而raw目錄不行
解析AIDL文件生成對(duì)應(yīng)的java文件
使用aidl工具生成AIDL.java文件,這個(gè)很簡(jiǎn)單,應(yīng)該就是通過(guò)一個(gè)模板文件了
java文件編譯成class
使用javac工具來(lái)編譯java文件為class文件了
編譯后可對(duì)代碼進(jìn)行混淆處理,主要包括刪除無(wú)用類、字節(jié)碼優(yōu)化、重命名等操作,只需在build.gradle中配置混淆規(guī)則即可
class轉(zhuǎn)dex
這里主要使用dx來(lái)講java字節(jié)碼轉(zhuǎn)成Dalvik字節(jié)碼
打包apk
調(diào)用ApkBuilderMain這個(gè)java類來(lái)打包資源以及dex文件和so文件等
簽名
對(duì)apk進(jìn)行簽名
優(yōu)化并生成apk
使用zipalign來(lái)優(yōu)化,具體怎么優(yōu)化,可以參考https://developer.android.com/studio/command-line/zipalign
參考文章:
https://blog.csdn.net/jason0539/article/details/44917745