APK文件淺析-打包流程

本文從宏觀視角來看看APK文件結構及其設計思想,藉助一個簡單的「Hello Android」爲例說明java

APK文件結構

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打開,基本組成如圖: 微信

Hello Android
再打開一個下載好的比較複雜的APK(微信), 如圖
WeChat
不管是簡單的Hello world 仍是複雜的WeChat,能夠看出其主要組成包括:

  1. AndroidManifest.xml :用於聲明應用包名信息、相關的使用權限、四大組件、android sdk版本等;
  2. res目錄:包含程序主要資源文件,包括res/layout、res/drawable等,主要是佈局文件和圖片等資源。(微信是對資源作了混淆,字符串裁剪,上圖中的r=res);
  3. resources.ars:資源映射表,包含一部分編譯資源(res/value)和資源路徑, 能夠經過資源R.java中的ID映射到對應的資源文件或者值;
  4. assets目錄:包含不被壓縮的原始文件,主要是一些多媒體文件,或者附加文件;
  5. lib目錄:使用到的各類.so連接庫;
  6. Classes.dex:打包好的程序代碼,若是是複雜的應用會進行分包,包含多個dex文件(微信);
  7. META-INF目錄:主要包含APK的簽名信息
    • MANIFEST.MF:清單文件,當前APK中全部文件清單及其對應hash值;
    • CERT.SF:上述清單文件中的每條信息的hash值;
    • CERT.RSA:對CERT.SF文件的數字簽名以及簽名時所用的數字證書;

那這些文件究竟是怎麼生成的,接下來看看一個APK文件的構建流程。框架

APK打包流程

Android Studio默認採用gradle組織完成打包過程,對開發者來講簡單的執行相關的task便可,這種透明的打包過程也讓咱們忽略了不少細節,這裏咱們以上述APK文件結構做爲對照,來一窺源碼結構變成最終的APK文件的過程。ide

1. AndroidManifest.xml

Hello Android爲例,對比源碼中的AndroidManifest.xml 與 APK中的AndroidManifest.xml 能夠明顯看出 工具

AndroidManifest
會新增一些之類的標籤,以前的theme、label等字符串被替換爲具體的引用。這一過程發生在資源打包過程當中,對這一過程不熟悉的可參考我以前的 資源打包流程, 簡單說就是gradle在打包過程當中會經過命令行啓動 aapt工具, aapt在打包資源過程當中會進行Merge Manifest,對AndroidManifest.xml文件進行修改。 注意這裏是經過AndroidStudio自帶的分析器打開APK才能明確看到AndroidManifest.xml中的內容,若是隻是簡單的解壓APK後AndroidManifest.xml被編譯成了二進制文件。

2. res/

對比源碼和打包後res目錄的變化,也會發現res中的drawable中的圖片等資源沒有發生明顯變化(其實會部分壓縮),layout/下的xml文件也發生了相似AndroidManifest.xml的字符串替換和編譯,變成了二進制文件,而values/不見了。對res/的處理也發生在aapt編譯資源的過程當中,對其中的xml文件進行編譯和字符串裁剪,部分xml資源會被編譯進resources.arsc。佈局

3. resources.arsc

resources.arsc 也是個二進制文件,是aapt打包資源過程當中的產物,同時伴隨着上述資源文件的編譯和壓縮,其中res/value其實就編譯進了resources.arsc, 其餘的資源文件的id和路徑對應關係也寫進了這個文件,便於運行時訪問。gradle

對資源打包和訪問不太熟悉的能夠參考:優化

Android 資源框架:資源打包流程ui

Android 資源框架:資源的運行時訪問

4. assets/

目錄中的文件未發生變化

5. lib/

無變化

6. Classes.dex

dex文件是Dalvik 和 ART 可執行格式。相較於JVM,dex將多個class文件打包到了一塊兒,所以從Java文件到dex,須要經歷java--->class-->dex的過程;

  • 若是用到了AIDL,經過sdk/build-tools/xxx/aidl 工具解析aidl文件,生成對應的Java文件;
  • Compile全部的 Java文件生成 .class文件;
  • 經過dx腳本,將全部class文件包括第三方Jar包等處理爲dex文件,若是配置了multidex, 可能會生成多個classes.dex文件。dx及其餘相關腳本位於sdk/build-tools/xxx/

相較於class文件,dx工具在生成dex文件的過程當中,會對字符常量池和一些冗餘信息會進行壓縮,結構上比class文件也更加緊湊。

7. 打包

經過apkbuilder工具,將aapt處理後的相關資源文件和利用dx處理生成的Classes.dex打包生成APK文件,apkbuilder工具也位於 sdk/build-tools/

8. 對APK進行對齊處理

藉助zipalign工具,對APK文件進行對齊處理:

zipalign 是一種歸檔對齊工具,可對 Android 應用文件進行重要的優化。其目的是要確保全部未壓縮數據的開頭均相對於文件開頭部分執行特定的對齊。具體來講,它會使 APK 中的全部未壓縮數據(例如圖片或原始文件)在 4 字節邊界上對齊。這樣一來,便可使用 mmap() 直接訪問全部部分,即便其中包含具備對齊限制的二進制數據也不要緊。這樣作的好處是能夠減小運行應用時消耗的 RAM 容量。

9.簽名

經過apksigner工具,對生成的APK文件進行簽名;

以上,咱們就獲得了一個包含 代碼 + 資源 + 簽名信息的可獨立安裝運行的APK文件。

以上用到的相關腳本及工具均位於 sdk/build-tools/

sdk build-tools
具體的細節可參考其對應source code

總結

咱們首先分析了一個基本的APK文件的組成部分,以後拆解了每個組成文件的生成過程及其相關腳本。若是你對aaptdxapksigner的具體工做流程感興趣,能夠查找並閱讀其源碼。再來看官方打包流程圖,相信你會更加清晰!

apk build

相關閱讀:

Android MultiDex 分包及加載原理

Android 資源框架:資源打包流程

Android 資源框架:資源的運行時訪問

相關文章
相關標籤/搜索