apk 是Android Package的簡寫, 在平時(shí)的開發(fā)過程中,通過點(diǎn)擊 Run app 按鈕 或者 在命令行中輸入
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對(duì)這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長期合作伙伴,公司提供的服務(wù)項(xiàng)目有:國際域名空間、網(wǎng)絡(luò)空間、營銷軟件、網(wǎng)站建設(shè)、肥西網(wǎng)站維護(hù)、網(wǎng)站推廣。
這樣Android Studio就會(huì)啟動(dòng)構(gòu)建流程,最終輸出一個(gè)我們想要的APK。
直達(dá)官網(wǎng)介紹
對(duì)于小白來說,上面一張圖已經(jīng)可以解釋apk的構(gòu)建過程了,不過對(duì)于Andoid開發(fā)者而言還需要了解一些更詳細(xì)的構(gòu)建過程。
詳細(xì)的對(duì)應(yīng)步驟 和 使用工具如下:
資源文件(res文件夾下的文件)通過 AAPT(Android Asset Packaging Tool)打包生成R.java類(資源索引表)、.arsc資源文件 和res文件。
resources.arsc 是一個(gè)App的資源索引表,通過R.java 文件 和 resources.arsc 可以定位到資源的內(nèi)存地址,resources.arsc文件的作用是通過一樣的ID,根據(jù)不同的配置索引到最佳的資源顯示在UI中。
AIDL (Android Interface Definition Language), 是Android接口定義語言,是Android提供的IPC (Inter Process Communication,進(jìn)程間通信)的一種獨(dú)特實(shí)現(xiàn)。
如果有aidl文件,這個(gè)階段會(huì)生成對(duì)應(yīng)的Java接口文件。
R.java文件、工程源碼文件、aidl.java文件, 在這一步通過javac生成.class文件。
源碼.class文件和第三方j(luò)ar或者library通過dx工具打包成dex文件
Android系統(tǒng)的Dalvik虛擬機(jī)的可執(zhí)行文件為DEX格式,所以這里會(huì)將上一步中生成的.class文件 和 引用的第三方j(luò)ar等過程中的.class 一起通過dx工具打包成dex文件
apkbuilder工具會(huì)將所有沒有編譯的資源、.arsc資源、.dex文件打包到一個(gè)完成apk文件中
tips:
apksigner工具會(huì)對(duì)未簽名的apk驗(yàn)證簽名。得到一個(gè)簽名后的apk(signed.apk)
apksigner 是google 退出的V2簽名方式
Jarsigner 是之前一直使用的V1簽名方式
可以通過在命令行中輸入apksigner --help來獲取詳情信息,如果沒有特殊需求,使用下面命令即可完成簽名
release mode 下使用 aipalign進(jìn)行align,即對(duì)簽名后的apk進(jìn)行對(duì)齊處理
所謂對(duì)齊,主要過程是將APK包中所有的資源文件距離文件起始偏移為4字節(jié)整數(shù)倍,這樣通過內(nèi)存映射訪問apk文件時(shí)的速度會(huì)更快。對(duì)齊的作用主要是為了減少運(yùn)行時(shí)內(nèi)存的使用。
zipalign是一個(gè)android平臺(tái)上整理APK文件的工具,它對(duì)apk中未壓縮的數(shù)據(jù)進(jìn)行4字節(jié)對(duì)齊,對(duì)齊后就可以使用mmap函數(shù)讀取文件,可以像讀取內(nèi)存一樣對(duì)普通文件進(jìn)行操作。如果沒有4字節(jié)對(duì)齊,就必須顯式的讀取,這樣比較緩慢并且會(huì)耗費(fèi)額外的內(nèi)存。
參考文章:
Android-Studio配置構(gòu)建
淺談Android打包流程
apk打包流程
END!
下圖的是官網(wǎng)對(duì)于Android編譯打包流程的介紹。
官方的介紹非?;\統(tǒng),簡而言之,其大致流程就是:
編譯--DEX--打包--簽名和對(duì)齊
(好像什么都沒Get到,有一種意猶未盡的感覺……)
來一張外國大神的圖片(注:這張圖少了簽名的步驟)
用文字解釋一下上圖的流程:
首先,我們整理一下編譯的輸入部分是什么(圖中黃色部分):
接下來的步驟:
好了,編譯打包的詳細(xì)流程說完了,接下來我們看看是否能回答開篇的那些問題。
答:aapt工具對(duì)于每個(gè)資源文件生成了唯一的ID,這些ID保存在R.java文件中。如下是R.java文件的內(nèi)容:
資源ID是一個(gè)4字節(jié)的無符號(hào)整數(shù),在R.java文件中用16進(jìn)制表示。其中,最高的1字節(jié)表示Package ID,次高1個(gè)字節(jié)表示Type ID,最低2字節(jié)表示Entry ID。
只有一個(gè)ID如何能引用到實(shí)際資源呢?實(shí)際上aapt工具還生成了一個(gè)文件resources.arsc,相當(dāng)于一個(gè)資源索引表,或者你理解成一個(gè)map也行,map的key是資源ID,value是資源在apk文件中的路徑。resources.arsc里面還有其他信息,這個(gè)就不多說了。
通過R.java文件和resources.arsc配合,就能引用到實(shí)際的資源文件。
答:第7步已經(jīng)闡述了對(duì)齊所做的工作,為什么要進(jìn)行對(duì)齊,這是為了加快資源的訪問速度。如果每個(gè)資源的開始位置都是上一個(gè)資源之后的 4*n字節(jié),那么訪問下一個(gè)資源就不用遍歷,直接跳到4*n字節(jié)處判斷是不是一個(gè)新的資源即可。
如果舉例子,那么對(duì)齊有點(diǎn)類似于資源數(shù)組化,數(shù)組的訪問速度當(dāng)然比鏈表快。
答:xml里面都是各種字符,不利于快速遍歷。編譯成二進(jìn)制文件,用數(shù)字替換各種符號(hào),一方面能快速訪問,另一方面也能減少大小。
android源碼目錄下的build/envsetup.sh文件,描述編譯的命令
- m:?????? Makes from the top of the tree.
- mm:????? Builds all of the modules in the current directory.
- mmm:???? Builds all of the modules in the supplied directories.
要想使用這些命令,首先需要設(shè)置android腳本編譯環(huán)境,在源碼根目錄執(zhí)行 source build/envsetup.sh
m:編譯所有的模塊
mm:編譯當(dāng)前目錄下的模塊,當(dāng)前目錄下要有Android.mk文件
mmm:編譯指定路徑下的模塊,指定路徑下要有Android.mk文件
下面舉個(gè)例子說明,假設(shè)我要編譯android下的\framework\av\cmds\screenrecord模塊,
當(dāng)前目錄為源碼根目錄,方法如下:
1、source build/envsetup.sh
2、mmm framework/av/cmds/screenrecord
或者 :
1、source build/envsetup.sh
2、cd framework/av/cmds/screenrecord
3、mm
Android 系統(tǒng)提供了三種指令用于編譯,他們分別為make、mmm、mm,這三個(gè)指令編譯的優(yōu)缺點(diǎn)如下:
例如:make MediaProvider z這種模式對(duì)應(yīng)于單個(gè)模塊的編譯。它的優(yōu)點(diǎn)是:會(huì)把該模塊依賴的其他模塊一起跟著編譯。例如:make libmedia 就會(huì)把libmedia依賴庫全部編譯好。當(dāng)然缺點(diǎn)也會(huì)很明顯,那就是它會(huì)搜索整個(gè)源碼來定位MediaProvider 模塊所使用的Android.mk文件。并且還要判斷該模塊依賴的其他模塊是否有修改。所以編譯時(shí)間比較長。
注意:一般的編譯方式都會(huì)采用增量編譯,即只編譯發(fā)生變化的目標(biāo)文件,但有時(shí)則需要重新編譯所有目標(biāo)文件,那么就可以使用make 命令行的-B選項(xiàng)。例如:mm -B 模塊名,或者mm -B、mmm -B。在mm 和 mmm內(nèi)部也是調(diào)用make命令的,而make的-B選項(xiàng)將強(qiáng)制編譯所有的目標(biāo)文件。
您的開發(fā)編譯機(jī)必須達(dá)到或超出以下硬件要求:
如果是 Gingerbread (2.3.x) 及更高版本(包括 master 分支),需要使用 64 位環(huán)境。如果是較低的版本,則可以在 32 位系統(tǒng)中進(jìn)行編譯。
如果是校驗(yàn)代碼,至少需要 100GB 可用磁盤空間;如果要進(jìn)行編譯,則還需要 150GB。如果要進(jìn)行多次編譯或使用 ccache,則需要更多空間。
如果您在虛擬機(jī)中運(yùn)行 Linux,則至少需要 16GB 的 RAM/交換空間(swap)。
在編譯Android系統(tǒng)時(shí),需要先執(zhí)行2條命令,來設(shè)置必要的環(huán)境變量。
接下來就可以執(zhí)行make系列命令,來完成不同的需要。
make clean 用來清除編譯歷史,開始一個(gè)全新的編譯。
make -j 或 make -j8 啟動(dòng)編譯過程。 -j 后面的數(shù)字代表要使用的cpu thread的數(shù)目。
在完成了全編譯后,才能執(zhí)行生成OTA升級(jí)包的操作。
注意事項(xiàng):