本文從宏觀視角來看看APK文件結構及其設計思想,藉助一個簡單的「Hello Android」爲例說明java
An APK file contains all of a program’s code (such as .dex file), resources, assets, certificates, and manifest file.android
APK文件自己是個壓縮文件,咱們能夠經過一個簡單的Hello Android示例和一個複雜的應用,對比其對應的APK文件。 首先新建一個簡單的Hello Android項目,build出一個APK文件後拖到AS中利用自帶的apkanalyzer打開,基本組成如圖: 微信
再打開一個下載好的比較複雜的APK(微信), 如圖 不管是簡單的Hello world 仍是複雜的WeChat,能夠看出其主要組成包括:那這些文件究竟是怎麼生成的,接下來看看一個APK文件的構建流程。框架
Android Studio默認採用gradle組織完成打包過程,對開發者來講簡單的執行相關的task便可,這種透明的打包過程也讓咱們忽略了不少細節,這裏咱們以上述APK文件結構做爲對照,來一窺源碼結構變成最終的APK文件的過程。ide
以Hello Android爲例,對比源碼中的AndroidManifest.xml 與 APK中的AndroidManifest.xml 能夠明顯看出 工具
會新增一些之類的標籤,以前的theme、label等字符串被替換爲具體的引用。這一過程發生在資源打包過程當中,對這一過程不熟悉的可參考我以前的 資源打包流程, 簡單說就是gradle在打包過程當中會經過命令行啓動 aapt工具, aapt在打包資源過程當中會進行Merge Manifest,對AndroidManifest.xml文件進行修改。 注意這裏是經過AndroidStudio自帶的分析器打開APK才能明確看到AndroidManifest.xml中的內容,若是隻是簡單的解壓APK後AndroidManifest.xml被編譯成了二進制文件。對比源碼和打包後res目錄的變化,也會發現res中的drawable中的圖片等資源沒有發生明顯變化(其實會部分壓縮),layout/下的xml文件也發生了相似AndroidManifest.xml的字符串替換和編譯,變成了二進制文件,而values/不見了。對res/的處理也發生在aapt編譯資源的過程當中,對其中的xml文件進行編譯和字符串裁剪,部分xml資源會被編譯進resources.arsc。佈局
resources.arsc 也是個二進制文件,是aapt打包資源過程當中的產物,同時伴隨着上述資源文件的編譯和壓縮,其中res/value其實就編譯進了resources.arsc, 其餘的資源文件的id和路徑對應關係也寫進了這個文件,便於運行時訪問。gradle
對資源打包和訪問不太熟悉的能夠參考:優化
目錄中的文件未發生變化
無變化
dex文件是Dalvik 和 ART 可執行格式。相較於JVM,dex將多個class文件打包到了一塊兒,所以從Java文件到dex,須要經歷java--->class-->dex的過程;
相較於class文件,dx工具在生成dex文件的過程當中,會對字符常量池和一些冗餘信息會進行壓縮,結構上比class文件也更加緊湊。
經過apkbuilder工具,將aapt處理後的相關資源文件和利用dx處理生成的Classes.dex打包生成APK文件,apkbuilder工具也位於 sdk/build-tools/
藉助zipalign工具,對APK文件進行對齊處理:
zipalign 是一種歸檔對齊工具,可對 Android 應用文件進行重要的優化。其目的是要確保全部未壓縮數據的開頭均相對於文件開頭部分執行特定的對齊。具體來講,它會使 APK 中的全部未壓縮數據(例如圖片或原始文件)在 4 字節邊界上對齊。這樣一來,便可使用 mmap() 直接訪問全部部分,即便其中包含具備對齊限制的二進制數據也不要緊。這樣作的好處是能夠減小運行應用時消耗的 RAM 容量。
經過apksigner工具,對生成的APK文件進行簽名;
以上,咱們就獲得了一個包含 代碼 + 資源 + 簽名信息的可獨立安裝運行的APK文件。
以上用到的相關腳本及工具均位於 sdk/build-tools/
具體的細節可參考其對應source code咱們首先分析了一個基本的APK文件的組成部分,以後拆解了每個組成文件的生成過程及其相關腳本。若是你對aapt、dx、apksigner的具體工做流程感興趣,能夠查找並閱讀其源碼。再來看官方打包流程圖,相信你會更加清晰!