Android 打包與APK安裝原理

一、APK安裝原理

二、APP啟動(dòng)流程優(yōu)化

三、Android App 的安裝過(guò)程

在分析安裝過(guò)程之前,需要先了解一下 Android 項(xiàng)目是如何經(jīng)過(guò)編譯->打包生成最終的?.apk?格式的安裝包颅崩。谷歌有一張官方圖片來(lái)描述?apk?的打包流程,如下圖所示蕊苗。

一個(gè)完整的 Android 項(xiàng)目可能包含多個(gè)?module沿后,而從宏觀上看每一個(gè)?module?中的內(nèi)容可以分為?2?部分:Resources?資源文件、Java?或者?Kotlin?源代碼岁歉。因此整個(gè)項(xiàng)目的編譯打包過(guò)程也是針對(duì)這?2?部分來(lái)完成得运。

編譯階段

Resources?資源文件

資源文件包括項(xiàng)目中?res?目錄下的各種?XML?文件膝蜈、動(dòng)畫(huà)、drawable?圖片熔掺、音視頻等饱搏。AAPT?工具負(fù)責(zé)編譯項(xiàng)目中的這些資源文件,所有資源文件會(huì)被編譯處理置逻,XML?文件(drawable?圖片除外)會(huì)被編譯成二進(jìn)制文件推沸,所以解壓?apk?之后無(wú)法直接打開(kāi)?XML?文件。但是?assets?和?raw?目錄下的資源并不會(huì)被編譯券坞,會(huì)被原封不動(dòng)的打包到?apk?壓縮包中鬓催。

資源文件編譯之后的產(chǎn)物包括兩部分:resources.arsc?文件和一個(gè)?R.java。前者保存的是一個(gè)資源索引表恨锚,后者定義了各個(gè)資源?ID?常量宇驾。這兩者結(jié)合就可以在代碼中找到對(duì)應(yīng)的資源引用

源碼部分

項(xiàng)目中的源代碼首先會(huì)通過(guò)?javac?編譯為?.class?字節(jié)碼文件,然后這些?.class?文件連同依賴(lài)的三方庫(kù)中的?.class?文件一同被?dx?工具優(yōu)化為?.dex?文件猴伶。如果有分包课舍,那么也可能會(huì)生成多個(gè)?.dex?文件。

實(shí)際上源代碼文件也包括?AIDL?接口文件編譯之后生成的?.java?文件他挎,Android?項(xiàng)目中如果包含?.aidl?接口文件筝尾,這些?.aidl?文件會(huì)被編譯成?.java?文件。

打包階段

最后使用工具?APK Builder?將經(jīng)過(guò)編譯之后的?resource?和?.dex?文件一起打包到?apk?中办桨,實(shí)際上被打包到?apk?中的還有一些其他資源筹淫,比如?AndroidManifest.xml?清單文件和三方庫(kù)中使用的動(dòng)態(tài)庫(kù)?.so?文件。

apk?創(chuàng)建好之后呢撞,還不能直接使用损姜。需要使用工具?jarsigner?對(duì)其進(jìn)行簽名,因?yàn)?Android?系統(tǒng)不會(huì)安裝沒(méi)有進(jìn)行簽名的程序殊霞。簽名之后會(huì)生成?META_INF?文件夾薛匪,此文件夾中保存著跟簽名相關(guān)的各個(gè)文件。

CERT.SF:生成每個(gè)文件相對(duì)的密鑰

MANIFEST.MF:數(shù)字簽名信息

xxx.SF:這是?JAR?文件的簽名文件

xxx.DSA:對(duì)輸出文件的簽名和公鑰脓鹃。

但是實(shí)際打包過(guò)程還會(huì)多一步?apk?優(yōu)化操作。就是使用工具?zipalign?對(duì)?apk?中的未壓縮資源(圖片古沥、視頻等)進(jìn)行對(duì)齊操作瘸右,讓資源按照?4?字節(jié)的邊界進(jìn)行對(duì)齊。這種思想同?Java?對(duì)象內(nèi)存布局中的對(duì)齊空間非常類(lèi)似岩齿,主要是為了加快資源的訪問(wèn)速度太颤。如果每個(gè)資源的開(kāi)始位置都是上一個(gè)資源之后的?4n?字節(jié),那么訪問(wèn)下一個(gè)資源就不用遍歷盹沈,直接跳到?4n?字節(jié)處判斷是不是一個(gè)新的資源即可龄章。

至此一個(gè)完整的?apk?安裝包就創(chuàng)建成功吃谣,一個(gè)完整的?apk?解壓縮之后的內(nèi)容如下所示:

PMS安裝過(guò)程概覽

當(dāng)我們點(diǎn)擊某一個(gè)?App 安裝包進(jìn)行安裝時(shí),首先會(huì)彈出一個(gè)系統(tǒng)界面指示我們進(jìn)行安裝操作做裙。這個(gè)界面是 Android Framework 中預(yù)置的一個(gè) Activity—PackageInstallerActivity.java岗憋。當(dāng)點(diǎn)擊安裝后,PackageInstallerActivity 最終會(huì)將所安裝的 apk 信息通過(guò) PackageInstallerSession 傳給 PMS锚贱,具體方法在 commitLocked 方法中仔戈,

圖中的?mPm 就是系統(tǒng)服務(wù) PackageManagerService。installStage 方法就是正式開(kāi)始 apk 的安裝過(guò)程拧廊。

整個(gè)?apk 的安裝過(guò)程可以分為兩大步:

拷貝安裝包监徘;

裝載代碼。

拷貝安裝包

從?installStage 方法開(kāi)始看起

圖中?1?處創(chuàng)建了類(lèi)型為?INIT_COPY?的?Message吧碾。

圖中?2?處創(chuàng)建?InstallParams凰盔,并傳入安裝包的相關(guān)數(shù)據(jù)。

Message?發(fā)送出去之后倦春,由?PMS?的內(nèi)部類(lèi)?PackageHandler?接收并處理户敬,

可以看出在?copyApk?方法中調(diào)用了?doCopyApk?方法,doCopyAPk?方法中主要做了?3?件事情:

圖中?1?處創(chuàng)建存儲(chǔ)安裝包的目標(biāo)路徑溅漾,實(shí)際上是?/data/app/?應(yīng)用包名目錄山叮;

圖中?2?處調(diào)用服務(wù)的?copyPackage?方法將安裝包?apk?拷貝到目標(biāo)路徑中;

圖中?3?處將?apk?中的動(dòng)態(tài)庫(kù)?.so?文件也拷貝到目標(biāo)路徑中添履。

裝載代碼

圖中?1?處執(zhí)行預(yù)安裝操作屁倔,主要是檢查安裝包的狀態(tài),確保安裝環(huán)境正常暮胧,如果安裝環(huán)境有問(wèn)題會(huì)清理拷貝文件锐借。

圖中?2?處是真正的安裝階段,installPackageTraceLI?方法中添加跟蹤?Trace往衷,然后調(diào)用?installPackageLI?方法進(jìn)行安裝钞翔。

圖中?3?處處理安裝完成之后的操作。

圖中?1?處調(diào)用?PackageParser?的?parsePackage?方法解析?apk?文件席舍,主要是解析?AndroidManifest.xml?文件布轿,將結(jié)果記錄在?PackageParser.Package?中。我們?cè)谇鍐挝募新暶鞯?Activity来颤、Service?等組件就是在這一步中被記錄到系統(tǒng)?Framework?中汰扭,后續(xù)才可以通過(guò)?startActivity?或者?startService?啟動(dòng)相應(yīng)的活動(dòng)或者服務(wù)。

圖中?2?處對(duì)?apk?中的簽名信息進(jìn)行驗(yàn)證操作福铅。collectCertificates?做簽名驗(yàn)證萝毛,collectManifestDigest?主要是做包的項(xiàng)目清單摘要的收集,主要適合用來(lái)比較兩個(gè)包的是否一樣滑黔。如果我們?cè)O(shè)備上已經(jīng)安裝了一個(gè)?debug?版本的?apk笆包,再次使用一個(gè)?release?版本的?apk?進(jìn)行覆蓋安裝時(shí)环揽,會(huì)在這一步驗(yàn)證失敗,最終導(dǎo)致安裝失敗庵佣。

圖中?3?處時(shí)執(zhí)行?dex?優(yōu)化歉胶,實(shí)際為?dex2oat?操作,用來(lái)將?apk?中的?dex?文件轉(zhuǎn)換為?oat?文件秧了。

圖中?4?處調(diào)用?installNewPackageLI?方法執(zhí)行新?apk?的安裝操作

installNewPackageLI?方法負(fù)責(zé)完成最后的?apk?安裝過(guò)程跨扮,具體代碼如下:

解釋說(shuō)明:

scanPackageLI?繼續(xù)掃描解析?apk?安裝包文件,保存?apk?相關(guān)信息到?PMS?中验毡,并創(chuàng)建?apk?的?data?目錄衡创,具體路徑為?/data/data/應(yīng)用包名。

updateSettingsLI?如果安裝成功晶通,更新系統(tǒng)設(shè)置中的應(yīng)用信息璃氢,比如應(yīng)用的權(quán)限信息。

deletePackageLI?如果安裝失敗狮辽,則將安裝包以及各種緩存文件刪除

至此整個(gè)?apk?的安裝過(guò)程結(jié)束一也,實(shí)際上安裝成功之后,還會(huì)發(fā)送一個(gè)?App?安裝成功的廣播?ACTION_PACKAGE_ADDED喉脖。手機(jī)桌面應(yīng)用注冊(cè)了這個(gè)廣播椰苟,當(dāng)接收到應(yīng)用安裝成功之后,就將?apk?的啟動(dòng)?icon?顯示在桌面上树叽。

總結(jié)

這節(jié)課主要介紹了一個(gè)?Android?項(xiàng)目從編譯成?apk?文件舆蝴,然后被安裝到手機(jī)設(shè)備上的簡(jiǎn)要過(guò)程。其中編譯分?2?塊內(nèi)容:資源?+?源代碼题诵。并且生成?apk?之后還要經(jīng)過(guò)簽名洁仗、對(duì)齊等操作。apk?安裝也分?2?塊進(jìn)行:安裝包拷貝和代碼裝載性锭。

可以關(guān)注我的公眾號(hào):Android架構(gòu)師成長(zhǎng)之路

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末赠潦,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子草冈,更是在濱河造成了極大的恐慌她奥,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件怎棱,死亡現(xiàn)場(chǎng)離奇詭異方淤,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)蹄殃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)你踩,“玉大人诅岩,你說(shuō)我怎么就攤上這事讳苦。” “怎么了吩谦?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵鸳谜,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我式廷,道長(zhǎng)咐扭,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任滑废,我火速辦了婚禮蝗肪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蠕趁。我一直安慰自己薛闪,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布俺陋。 她就那樣靜靜地躺著豁延,像睡著了一般。 火紅的嫁衣襯著肌膚如雪腊状。 梳的紋絲不亂的頭發(fā)上诱咏,一...
    開(kāi)封第一講書(shū)人閱讀 51,754評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音缴挖,去河邊找鬼袋狞。 笑死,一個(gè)胖子當(dāng)著我的面吹牛醇疼,可吹牛的內(nèi)容都是我干的硕并。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼秧荆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼倔毙!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起乙濒,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤陕赃,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后颁股,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體么库,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年甘有,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了诉儒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡亏掀,死狀恐怖忱反,靈堂內(nèi)的尸體忽然破棺而出泛释,到底是詐尸還是另有隱情,我是刑警寧澤温算,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布怜校,位于F島的核電站,受9級(jí)特大地震影響注竿,放射性物質(zhì)發(fā)生泄漏茄茁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一巩割、第九天 我趴在偏房一處隱蔽的房頂上張望裙顽。 院中可真熱鬧,春花似錦喂分、人聲如沸锦庸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)甘萧。三九已至,卻和暖如春梆掸,著一層夾襖步出監(jiān)牢的瞬間扬卷,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工酸钦, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留怪得,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓卑硫,卻偏偏與公主長(zhǎng)得像徒恋,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子欢伏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355