春節(jié)期間哪雕,在家看過(guò)分析Android中應(yīng)用啟動(dòng)器的代碼分析斯嚎“ず瘢回來(lái)后好久沒(méi)有鞏固列吼,也沒(méi)有再看。直到最近又看書,才想起來(lái)看了點(diǎn)東西全忘了陌选。這次就做個(gè)筆記咨油,以后回來(lái)也方便追溯。
一役电、APK文件結(jié)構(gòu)組成
APK文件我們可以理解成一些文件的集合在一起的一種特殊的壓縮包文件法瑟,拿到apk文件后,可以將其后綴名修改為.zip窝剖,然后將其解壓查看里面的目錄文件組成酥夭。
- AndroidManifest.xml文件是Android項(xiàng)目的配置文件熬北,組件聲明,版本號(hào),版本名稱讶隐,權(quán)限列表等信息都會(huì)在該文件中進(jìn)行說(shuō)明整份。
- META-INF 該目錄下存放的是簽名信心,保證應(yīng)用的安全性火俄。
- classes.dex 該文件是應(yīng)用中的java代碼編譯后可運(yùn)行在Dalvik虛擬機(jī)上的文件讲冠。相較于運(yùn)行在jvm上的class文件而言,dex文件經(jīng)過(guò)了進(jìn)一步的優(yōu)化谱仪,速度快,體積小等特點(diǎn)嗦随。也可以說(shuō)是專門為移動(dòng)設(shè)備而設(shè)計(jì)的敬尺。
- res目錄。該目錄存放的是應(yīng)用中使用到的資源文件署恍,比如圖片蜻直,布局等文件概而。
- resources.arc 該文件用于存放應(yīng)用內(nèi)使用到的字符串,尺寸到腥,顏色等資源乡范。
二、應(yīng)用安裝進(jìn)程
當(dāng)一個(gè)apk文件被拷貝到應(yīng)用目錄下面時(shí)渠脉,系統(tǒng)會(huì)自動(dòng)識(shí)別該動(dòng)作并且使用包管理器進(jìn)行安裝瓶佳,包管理器能夠監(jiān)測(cè)到應(yīng)用目錄下的改變。應(yīng)用安裝程序會(huì)借助系統(tǒng)包管理器中的installPackage()方法为朋;絕大多數(shù)的系統(tǒng)應(yīng)用都放在/system/app目錄下厚脉,另外在/system/priv-app目錄下存放的是系統(tǒng)的核心應(yīng)用,此目錄下的應(yīng)用可以使用系統(tǒng)級(jí)別的權(quán)限霞溪;Android中4.4版本開始添加的/system/priv-app目錄。上面提到的installPackage()方法是一系列的方法坊饶,這些方法在PackageManagerService中進(jìn)行了代碼實(shí)現(xiàn)殴蓬;
安裝程序的過(guò)程大概分為以下幾個(gè)步驟:
1.PackageInstallerActivity中首先會(huì)檢查要安裝的應(yīng)用是否是可信任的程序科雳;
2.PackageInstallerActivity中執(zhí)行解析方法,該方法會(huì)解析apk文件,從其AndroidManifest.xml文件中獲取其中列出的所有權(quán)限請(qǐng)求列表球散;
3.PackageInstallerActivity將應(yīng)用所申請(qǐng)的權(quán)限以列表的形式提示給用戶蕉堰,也就是我們安裝時(shí)看到的權(quán)限列表界面;
4.接下來(lái)就進(jìn)入了正式的安裝過(guò)程冰寻。開始安裝后皿渗,系統(tǒng)會(huì)將apk文件拷貝到/data/app/目錄下,因?yàn)榘惭b是一個(gè)耗時(shí)過(guò)程划乖,所以PackageManagerService會(huì)暫時(shí)生成一個(gè).tmp臨時(shí)文件挤土;
5.安裝進(jìn)程通過(guò)調(diào)用PackageManagerService中的scanPackageLI()方法來(lái)進(jìn)行包瀏覽;
6.創(chuàng)建存儲(chǔ)應(yīng)用數(shù)據(jù)的目錄仰美;
7.為安裝的應(yīng)用生成優(yōu)化后的dex文件代碼咖杂;我們提到過(guò)dex文件是Dalvik虛擬機(jī)能夠直接運(yùn)行的文件。
8.安裝應(yīng)用的最后一步止邮,是將安裝的應(yīng)用的包名,權(quán)限列表等信息更新到/data/system/packages.xml文件中屈扎,該文件中存儲(chǔ)了設(shè)備上安裝的所有應(yīng)用的包名及權(quán)限聲明等信息撩匕;
另外:
Android應(yīng)用還允許自定義權(quán)限,設(shè)備上安裝應(yīng)用時(shí)模蜡,子定義權(quán)限是以先注冊(cè)的為優(yōu)先級(jí)的扁凛;如果后安裝的應(yīng)用中包含了有已安裝注冊(cè)的自定義權(quán)限相同名字的權(quán)限谨朝,就會(huì)提示,以先注冊(cè)的為準(zhǔn)则披。
9.所有需要進(jìn)行的操作都完成后洗出,PackageManagerService會(huì)發(fā)送一個(gè)廣播ACTION_PACKAGE_ADDED,通知有需要更新的組件進(jìn)行更新翩活,比如Luncher;
二、應(yīng)用更新過(guò)程
應(yīng)用的更新過(guò)程和安裝的過(guò)程大致上是相似的隅茎。步驟也是遵循安裝應(yīng)用的步驟辟犀。
1.首先第一步,系統(tǒng)會(huì)進(jìn)行包名的簽名驗(yàn)證魂毁,判斷將要安裝的應(yīng)用和已安裝存在的應(yīng)用的簽名是否是同一個(gè)簽名出嘹;
2.接下來(lái)進(jìn)行真正的更新操作税稼。系統(tǒng)一次只能更新一個(gè)應(yīng)用垮斯,第一步就會(huì)殺掉其他正在更新的進(jìn)程只祠;
3.將將要更新的應(yīng)用包從內(nèi)核結(jié)構(gòu)和相關(guān)數(shù)據(jù)庫(kù)中移除抛寝,這一步移除的其實(shí)就是應(yīng)用注冊(cè)到內(nèi)核的所有組件;
4.接下來(lái)和安裝應(yīng)用時(shí)一樣晶府,PackageManagerService會(huì)觸發(fā)scanPackageLI()方法來(lái)瀏覽是否有其他額外的權(quán)限钻趋;
5.解析AndroidManifest.xml文件,為權(quán)限重新賦予權(quán)限书劝;
6.最后,將包名信息及權(quán)限列表等內(nèi)容更新保存到/data/system/packages.xml文件中并且PackageManagerService會(huì)接著發(fā)送一個(gè)PACKAGE_REPLACED的廣播猾昆;
命令筆記:
adb中pm有很多的命令:
pm list permissions 列出設(shè)備中的所有權(quán)限
pm list packages 列出設(shè)備中安裝的所有應(yīng)用的包名
pm install packagename 安裝某個(gè)應(yīng)用
pm uninstall packagename 卸載某個(gè)應(yīng)用
pm命令還有很多很多垂蜗,pm help 可以查看pm相關(guān)命令。