一文看懂 Android APK 安裝的原理 [復制鏈接]

2019-8-27 10:37
hardwork 閱讀:602 評論:1 贊:0
Tag:  APK

前言

大家有沒有想過一個應用的APK是怎么被安裝到安卓手機上的,安裝的本質是什么?我們知道,Windows應用程序的安裝包是一個可執行的壓縮包,安裝的過程是把壓縮包中的數據和依賴庫拷貝到安裝目錄,再在桌面或啟動欄創建快捷方式,那么安卓的APK安裝過程是不是也是這樣的呢?本文將為大家解答這些問題。

APK包的構成

首先,我看一下APK包的構成,Android的APK包和Windows應用程序安裝包是不同的,它只是個簡單的壓縮包,沒有可執行的能力,我們還可以用zip工具直接解壓它。

一個APK包含以下這些文件:

  • META-INF目錄:包含兩個簽名文件(CERT.SF和CERT.RSA),以及一個manifest文件(MANIFEST.MF)
  • assets目錄:包含工程中的asset目錄下的文件,可以使用AssetManager獲取
  • res目錄:包含那些沒有被編譯到resources.arsc的資源
  • lib目錄:包含適用于不同處理器的第三方依賴庫,這里邊可以有多個子目錄,比如armeabi, armeabi-v7a, arm64-v8a, x86, x86_64, 以及mips
  • resources.arsc文件:存儲編譯好的資源,包括項目工程中的res/values目錄里的xml文件,它們都被編譯成二進制格式,也包括一些路徑,指向那些沒有被編譯的資源,比如layout文件和圖片
  • classes.dex文件:項目中的java類都被編譯到該dex文件,這個文件可以被Android的Dalvik/ART虛擬機解析。
  • AndroidManifest.xml:二進制格式的manifest文件,這個文件是必須的。

這些文件是Android系統運行一個應用程序時會用到的數據和代碼,下面介紹系統如何安裝一個APK包。

安裝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提供了好幾個重要數據結構來保存這些數據,這些數據結構的相關信息如圖所示:

一文看懂 Android APK 安裝的原理

除了解析和保存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包中加載而已。


我來說兩句
您需要登錄后才可以評論 登錄 | 立即注冊
facelist
所有評論(1)
15801260778 2019-8-29 11:09
學習學習學習學習學習學習
回復
領先的中文移動開發者社區
18620764416
7*24全天服務
意見反饋:[email protected]

掃一掃關注我們

Powered by Discuz! X3.2© 2001-2019 Comsenz Inc.( 粵ICP備15117877號 )

阿拉斯加垂钓APP下载
pc蛋蛋 炒股配资 上海快三 上海时时彩 四川时时彩 二分彩 国际足球直播表 万宝配资 股票涨跌幅计算方法 4场进球 甘肃11选5 铁牛配资 顶级配资 内蒙古快三 重庆快乐10分 陕西快乐10分