Android項目構建Apk包流程

    好久都沒有寫博文了,主要是現在的工作重點是前端開發了,最近在學習webpack、weex等前端知識,說起weex,一直都在填坑中,目前還沒爬出來了!偷笑    好了,迴歸到本文的主題。之前也寫過有關Android打包apk方面的博文(使用Ant打包Apk打包Apk),但是都不夠細緻,比較籠統的介紹有關Apk打包的過程。所以,本文再次詳細描述下,Android項目構建Apk包流程。

一. 前言

    當我們使用Android Studio開發Android時,點擊運行按鈕,就會自動生成一個Apk文件,至於這個Apk是如何生成的,我們並不知道。而這個Apk中包含哪些東西呢?我們還是可以知道的。懷着好奇的心態,我們先來解壓一個Apk,看看他的廬山真面目。

    隨便找一個Apk文件,修改它的後綴名爲rar或者zip(其實Apk格式的文件就是一個壓縮文件)。如下圖所示,


其中 app-debug.rar文件是app-debug.apk修改後綴名後得到的,而app-debug文件夾是app-debug.rar文件解壓後生成的,


上面這張截圖是app-debug文件夾中的東東,可以看到大致包含5部分:

1. META-INF 文件夾,該文件夾中包含該Apk的簽名信息以及該Apk中所有文件的哈希值的計算結果;

2. res文件夾,存放的是資源文件,例如動畫、顏色、圖片和佈局等資源;下面給出一張res文件夾的中文件列表的截圖,


3. dex文件,該文件是適用於Dalvik虛擬機的字節碼文件,是通過dx工具將class文件轉化生成的;

4. resources.arsc,它是一個資源索引表,是由aapt根據res資源文件轉化生成的二進制文件;(下面會繼續補充該文件的作用);

5. AndroidManifest.xml,這個文件,我們都知道,這是Apk的清單文件,配置了各種權限以及註冊Activity、service等組件。(這個文件是壓縮處理過的,直接打開是亂碼,需要藉助其他工具)

二. 打包。

    首先來看一張Google官方給出的Apk構建流程,如下圖所示,


根據上圖,就能大致得出構建Apk的整個流程,

1. aapt工具將res中的資源生成 R.java文件和resources.arsc文件;

2. 如果有aidl,那麼aidl工具會將aidl接口轉化爲java類;

3. javac將所有的java類編譯爲class文件;

4. 如果有代碼混淆,則會加入代碼混淆;

5. dx.bat將所有的class文件轉化爲classes.dex文件;

6. ApkBuild將所有的資源(assets、so、jni)、resources.arcs以及上一步生成的dex文件,打包生成一個apk文件;

7. 對上一步生成的apk進行簽名;

8. 使用Zipalign對簽名後的apk進行優化。

下面詳細分析下各步驟的實現細節。

  2.1. 資源打包。(這一部分引用了網上一位博主的內容,詳細連接見下文)

開發app時,需要代碼和資源。最終生成的apk中代碼轉換爲了dex文件,那麼apk文件中的資源是否還是app開發時那些資源文件呢?或者說這些資源文件是否發生了什麼變化?引用老羅一張關於資源打包過程以及查找的圖:


從上圖可以看出:
1). 除了assets和res/raw資源被原裝不動地打包進APK之外,其它的資源都會被編譯或者處理.xml文件會被編譯爲二進制的xml,所以解壓apk後,無法直接打開xml文件。
2). 除了assets資源之外,其它的資源都會被賦予一個資源ID。
3). 打包工具負責編譯和打包資源,編譯完成之後,會生成一個resources.arsc文件和一個R.java,前者保存的是一個資源索引表,後者定義了各個資源ID常量,供在代碼中索引資源。
4). 應用程序配置文件AndroidManifest.xml同樣會被編譯成二進制的XML文件,然後再打包到APK裏面去。
5). 應用程序在運行時最終是通過AssetManager來訪問資源,或通過資源ID來訪問,或通過文件名來訪問。

在生成的apk中,只有assets和res/raw資源被原裝不動地打包進apk。其它的資源都會被編譯或者處理。可以使用如下命令查看apk中的文件列表:
aapt l -v apkfile
將apk直接解壓後,會發現xml都打不開,提示格式不對,因爲其已經變爲二進制xml了。另外PNG等圖片也會進行相應的優化。還有就是多了一個resources.arsc文件。
更多詳細的描述,可以查看Android6.0之App中的資源Rsources.arsc詳解這篇文章。

  2.2 aidl處理。

    aidl,全名Android Interface Definition Language,即Android接口定義語言。是我們在編寫進程間通信的時候,定義的接口。輸入:aidl後綴的文件。輸出:可用於進程通信的C/S端java代碼,位於build/generated/source/aidl。

    更多有關aidl的描述,請參考這篇Android IPC之AIDL淺談

  2.3 生成class文件。

    這一步是將整個代碼中的所有的java文件通過javac編譯爲class文件.

  2.4 生成dex文件。

    通過dex工具將項目中所有的class文件(也包含第三方庫中的)生成dex文件。

  2.5 生成Apk文件。

    通過apkbuilder工具 將所有的資源(res和assets)、resources.arsc和dex文件(可能是多個)打包生成Apk文件。

  2.6 Apk簽名。

    上一步生成的Apk文件是沒有簽名的,也就是說,是無法安裝到Android設備中的。android的應用程序需要簽名才能在android設備上安裝,簽名apk文件有兩種情況:一種是在調試程序時進行簽名,使用eclipse開發android程序時,在編譯調試程序時會自己使用一個debug.keystore對apk進行簽名;另一種是打包發佈時對程序進行簽名,這種情況下需要提供一個符合android開發文檔中要求的簽名文件。簽名的方法也分兩種:一種是使用jdk中提供的jarsigner工具簽名;另一種是使用android源碼中提供的signapk工具,它的代碼位於android系統源碼build\tools\signapk目錄下。

  2.7 Apk優化。

    這一步需要使用的工具爲zipalign,它位於android-sdk\tools目錄,源碼位於android系統源碼的build\tools\zipalign目錄,它的主要工作是將spk包進行對齊處理,使spk包中的所有資源文件距離文件起始偏移爲4字節整數倍,這樣通過內存映射訪問apk文件時速度會更快,驗證apk文件是否對齊過的工作由ZipAlign.cpp文件的verify()函數完成,處理對齊的工作則由process()函數完成。

    以上就是構建APk的全過程。相信看到這裏,小夥伴們對Apk的構建過程更清晰明瞭了!微笑

三. 補充。

3.1 aapt。

aapt----Android Asset Packaging Tool,即Android資源打包工具,位於SDK的build-tools目錄下。該工具的作用是將Android中的res資源生成R.java文件以及將資源文件生成一個二進制文件(resources.arsc)。在打包Apk時,需要使用到該工具。

    其中,R.java文件,相信開發Android的小夥伴們都知道,每當我們創建一個資源例如一個字符串,aapt就會在R.java文件中自動生成一個常量(ID),我們在使用某資源時,需要引用該資源對應的R.java文件的資源ID。下面是R.java文件的部分代碼截圖,


    resources.arsc,是aapt工具編譯資源時生成的重要文件。App資源能根據配置的變化,索引到相應的資源都要依賴它。例如Android設備語言,屏幕設備尺寸不同時,app通過同樣的ID但卻能找到不同的資源進行顯示。因爲 resources.arsc是二進制文件,所以解壓後,直接打開是亂碼。

總結下:

    R.java文件,定義了各個資源ID常量,在使用時需要使用該ID;resources.arsc,保存的是一個資源索引表。

3.2 Dalvik虛擬機。

Dalvik是Google公司自己設計用於Android平臺的Java虛擬機,它是Android平臺的重要組成部分,支持dex格式(Dalvik Executable)的Java應用程序的運行。dex格式是專門爲Dalvik設計的一種壓縮格式,適合內存和處理器速度有限的系統。Google對其進行了特定的優化,使得Dalvik具有高效、簡潔、節省資源的特點。從Android系統架構圖知,Dalvik虛擬機運行在Android的運行時庫層。

  當你的應用安裝在手機上後,應用程序的代碼將會以字節碼保存,每次冷啓動一個應用的時候,Dalvik虛擬機將字節碼轉換爲機器碼,然後交給硬件來執行;每次冷啓動的時候,Dalvik虛擬機就要重複將字節碼轉換爲機器碼的動作,而在這個階段,我們只能等待,靜靜的看着應用啓動,雖然每次都耗時較長,但是不會佔用過多的內存。因此在Android4.4發佈時,谷歌推出了新的Android虛擬機ART虛擬機,ART-Android Runtime,即Android運行時。ART虛擬機也是將字節碼轉換爲機器碼,但是它和Dalvik虛擬機的工作模式不一樣,在ART模式下,當你在安裝應用的時候,它就將字節碼轉換爲機器碼,並且保存起來,當在啓動一個應用的時候,就直接運行這個機器碼,因此,啓動速度就比較快。

有關Dalvik和ART的介紹,可以參考這篇文章 IT之家學院:認識Android中的Dalvik與ART虛擬機

  Java虛擬機-JVM和Dalvik虛擬機的區別。

    1). Java虛擬機運行的是Java字節碼(保存在class文件中),Dalvik運行的是Dalvik字節碼(由Java字節碼轉化而來,打包到DEX文件中)。

    2). Dalvik可執行文件更小。 
由於Android SDK中的dx文件對常量池進行了壓縮,使得相同字符串、常量在DEX文件中只出現一次。

    3). Java虛擬機與Daivik虛擬機架構不同 。
Java虛擬機基於棧結構,資源開銷大,Dalvik虛擬機基於寄存器結構,數據由寄存器直接傳遞,這樣的方式比基於棧結構的方式快得多。


以上內容參考了理解Android虛擬機體系結構

推薦一篇有關安卓手機爲什麼越用越卡越慢 問題原因探究




















發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章