大體瞭解Android應用安裝過程及原理

Android應用安裝的流程及路徑:

應用安裝涉及到如下幾個目錄:

system/app               系統自帶的應用程序,無法刪除

data/app                   用戶程序安裝的目錄,有刪除權限。安裝時把apk文件複製到此目錄

data/data                   存放應用程序的數據

Data/dalvik-cache   將apk中的dex文件安裝到dalvik-cache目錄下(dex文件是dalvik虛擬機的可執行文件,其大小約爲原始apk文件大小的四分之一)

安裝過程:

複製APK安裝包到data/app目錄下,解壓並掃描安裝包,把dex文件(Dalvik字節碼)保存到dalvik-cache目錄,並data/data目錄下創建對應的應用數據目錄。

卸載過程:

刪除安裝過程中在上述三個目錄下創建的文件及目錄。

Android應用安裝的四種方式:

1.系統應用安裝:開機時完成,沒有安裝界面
2.網絡下載應用安裝:通過market應用完成,沒有安裝界面
3.ADB工具安裝:沒有安裝界面。
4.第三方應用安裝:通過SD卡里的APK文件安裝,有安裝界面,由packageinstaller.apk應用處理安裝及卸載過程的界面。

安裝流程圖

APK文件結構

APK(Android Package),可以看做是一個zip壓縮包,可以通過解壓縮工具解開,其文件結構如下:

目錄 or 文件 描述
assert 存放的原生資源文件,通過AssetManager類訪問
lib native庫文件
META-INF 存放簽名信息,用來保證APK包的完整性和系統的安全。系統安裝APK時,應用管理器會按照對應算法對包裏文件做校驗,如果校驗結果與META-INF中內容不一致,則不會安裝這個APK。
res 種資源文件系統會在R.java裏面自動生成該資源文件的ID,所以訪問這種資源文件比較簡單,通過R.XXX.ID即可
AndroidManifest.xml 每個應用都必須定義和包含,描述應用的名字、版本權限、引用的庫文件等信息。apk中的AndroidManifest.xml經過壓縮,可以通過AXMLPrinter2工具解開。
classes.dex 是JAVA源碼編譯後生成的JAVA字節碼文件。但Android使用的dalvik虛擬機與標準的JAVA虛擬機不兼容,dex文件與class文件相比,不論是文件結構還是opcode都不一樣。
resources.arsc 編譯後的二進制資源文件。

安裝APK

安裝應用程序,最常用的方法就是在PC上運行命令adb install 加APK的文件路徑,回車等待Android設備安裝完成,安裝成功命令行會顯示Success。那麼其內部是怎樣的一個過程呢?

1. 將APK包push到手機

首先,adb會將PC端的APK文件push到Android設備的/data/local/tmp目錄下,一些手機會將拷貝的進度反饋給adb客戶端,於是PC上的命令行會展示拷貝的進度。

2. 執行pm命令

PC端的adb程序會向Android端的adbd發送shell:pm命令,於是adbd會向系統的PackageManagerService(PMS)進程發送消息,通知其安裝apk包。這裏可以有兩個理解:

理解一:我們平常也可以在adb shell上執行pm命令與PMS交互,那麼pm應該是個獨立的進程,adbd執行pm命令,是啓動了pm這個進程,這個進程再向PMS進程發送消息,通知其安裝APK。

理解二:adbd直接向PMS進程發送消息,通知其安裝APK。

不知哪個正確,這個有待繼續研究。

3. 觸發安裝過程

PMS首先將APK包拷貝到另外一個目錄/data/app,這個目錄是非系統應用的apk存放的目錄,與之相對應的,系統應用的apk存放的目錄是/system/frameworks、/system/app和/vendor/app。

PMS內部有個AppDirObserver類,其監聽着/data/app目錄的變化,當apk被複制到/data/app目錄之後,該類隨即觸發PMS對APK進行解析。

4. APK的解析

我們可以先想想,Android系統是如何啓動一個APP的?比如點擊屏幕上的應用圖標,然後一個Activity就被啓動了。這個過程中,桌面程序Launcher先是向ActivityManagerService(AMS)進程發送了一個Intent,AMS隨即會將這個Intent扔給PMS,PMS則解析這個Intent得到Activity的信息給到AMS,然後AMS會啓動一個空進程,並通知該進程創建該Activity。那麼PMS爲什麼會有這個Activity的信息呢?

這就是PMS解析APK要做的事情了,而解析APK的時機又要分成兩種場景:

1. 系統啓動時解析APK

Android系統在啓動的時候,會啓動一個system_server進程,這個進程駐留着系統多個重要的服務,其中便包含了與APK最相關的PackageManagerService服務,這個服務在啓動的時候,會掃描Android系統中幾個目標文件夾中的APK,對每個APK進行解析。

2. 安裝過程中解析APK

安裝一個apk的過程,PMS也會對這個APK進行解析,其調用的是PackageManagerService.java的scanPackageLI()方法,其實在系統啓動時掃描全部apk的過程也是調用該方法。

可以這樣理解,系統啓動的時候,是解析已經安裝的所有APK,而安裝單個APK時,則是用同樣的方法解析這個APK,過程是一樣的。

解析APK具體做的是什麼事情呢?

其中主要的過程就是解析APK中的AndroidManifest.xml文件,將APK的關鍵信息四大組件信息、權限信息等存儲在內存中的PackageParser對象中,PackageParser對象的結構如圖所示:

這個PackageParser包含了IntentFilter的信息,使得PMS可以根據Intent來獲取一個Activity的信息。那麼,PMS在得到PackageParser對象之後,接着會將這個APK的信息加入到PMS自身管理中去,比如將Activity的數據保存在mActivities對象中,將Provider的數據保存在mProviders對象中等,PKMS提供了好幾個重要數據結構來保存這些數據,這些數據結構的相關信息如圖所示:

除了解析和保存APK的核心數據,PMS還會創建應用程序目錄:/data/data/包名,同時提取apk中的dex文件並保存到/data/dalvik-cache中,如果該APK包含了native動態庫,則需要將它們從APK文件中解壓並複製到對應目錄中,以及對APK進行dex優化,還有其它一些細節比如APK簽名的校驗,殺死APK所在進程(覆蓋安裝的情況)等,安裝過程的最後,會發送ACTION_PACKAGE_ADDED廣播,通知所有其它應用有新應用安裝了。

總結

至此,APK安裝過程就結束了。縱觀整個過程,apk安裝的關鍵就是解析AndroidManifest.xml,將重要的信息保存在PMS進程的內存中,以保證後續啓動這個應用程序的組件時,可以在PMS中找到這個組件的信息。我們本來認爲的更重要的代碼只是進行dex優化後簡單地提取到一個目錄中而已,另外,APK中的資源並沒有被處理,而是在啓動應用進程的時候,動態去從APK包中加載而已。


重要參考:

應用程序安裝流程

一文看懂 Android APK 安裝的原理

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