android apk安裝過程原始碼解析
前言:
前一篇部落格分析了一下PackageManagerService是如何解析apk的以及我們如何解析未安裝apk中的androidManifest.xml檔案。解析完肯定要安裝的,索性寫一篇關於android系統是如何安裝我們apk的流程分析。不過這裡僅僅只分析java層面的程式碼,C層方面的就跳過了。
這裡有2個重點,第一個紅框可以看到與我們的PackageManagerService有關,獲取PackageManagerService的binder物件,與PackageManagerService進行通訊。並且如果這個物件為null 則輸出異常資訊直接返回,其實也不難理解,PackageManagerService把我們的apk給掃描了,那安裝應該也會在其中。所以這裡可以肯定的是apk的安裝實現就在我們的PackageManagerService中;第二點就是根據這個install標識來執行安裝的方法了。那我們就進入到runInstall()中來看下,它的內部是呼叫了PackageManagerService的什麼方法來進行apk安裝的。
runInstall()
從上面的runInstall()方法的程式碼可以看到 有3個標紅框的地方需要了解,第一個obs物件,用於接收PackageManagerService安裝結果,其實從第三個紅框就一目瞭然的瞭解INSTALL_SUCCEEDED,安裝成功!就輸出Success;第二個紅框就是透過binder來調起PackageManagerService中的installPackageWithVerificationAndEncryption()方法。
那接下來看下PackageManagerService中的installPackageWithVerificationAndEncryption()方法是如何操作的
這個方法程式碼並不是很多,重點在最後一部分,透過handler傳送一個INIT_COPY的訊息,訊息的內容是一個InstallParams物件。(這裡要注意下InstallParams,等下會說下這個)
那我們就只要找到handleMessage中處理這個INIT_COPY的訊息程式碼就行了
這裡值得一提的是,安裝apk的操作還需要一個服務,只有這個服務被bind了,才行進行下一步的工作,也就是透過handler繼續傳送一個訊息。(這個服務是com.android.defcontainer.DefaultContainerService這裡就不深層次分析了,它的作用就是用來解析APK,以及獲取推薦安裝路徑的,安裝的路徑與記憶體情況以及一些標識來決定)
繞來繞去,開啟服務之後又傳送了一個訊息,那隻好繼續看下這個MCS_BOUND訊息是如何處理的。
從程式碼中就能明顯看到,這裡又對服務進行了一次判斷,是否已經連線,所以這個服務於我們的apk安裝是共存的,其中mPendingInstalls就是用於儲存需要安裝的請求,只有當這個佇列為空時才斷開連線。(在INIT_COPY訊息處理中被新增到mPendingInstalls中的),然後又呼叫了HandlerParams的startCopy()方法執行安裝。
可以看到以下幾個重點
1.HandlerParams是個抽象類
2.箭頭那可以知道,這個安裝會嘗試4次,超過4次就GG了
3.執行handleStartCopy()方法
4.執行handleReturnCode()方法
在這之前值得一提的是前面installPackageWithVerificationAndEncryption()方法中透過handler傳送訊息,訊息的內容是InstallParams,而InstallParams又是繼承自HandlerParams這個抽象類,所以具體執行的是handleStartCopy()與handleReturnCode()的是InstallParams。
不過InstallParams這個方法的程式碼很長,這裡大致說下,InstallParams的handleStartCopy()的主要內容是透過com.android.defcontainer.DefaultContainerService來獲取apk的推薦安裝路徑,透過這個路徑來確定是內部安裝還是SD卡安裝,並且在這個方法的末尾,根據路徑來建立不同的InstallArgs,分別是FileInstallArgs/SdInstallArgs執行各自的copyApk()方法!
這裡就從FileInstallArgs的copyApk()這條路線來分析。
FileInstallArgs.copyApk()
這個方法的重點部分就在紅框位置,它的作用就是把我們的APK給複製到/data/app下,這個的路徑可以透過context.getPackageCodePath()獲取到,命名規則一般都是XXX.base.apk,不過這裡是個臨時檔案,在安裝的時候會對其進行改名操作。
到這就分析完了InstallParams的handleStartCopy()方法,還有一個重點部分是handleReturnCode方法,所以接著分析handleReturnCode();
這裡很簡單,呼叫了processPendingInstall()方法
這裡分為兩部分:
第一張圖可以看到標紅框部分執行了doPreInstall()和installPackageLI(),doPostInstall();
doPreInstall和doPostInstall內部很簡單,他的作用就是把我們安裝過程中的臨時檔案刪除,installPackageLI就是我們的正真安裝操作。
第二張圖則是安裝之後,傳送一個POST_INTALL訊息,告訴系統是否安裝完畢。
一系列的安裝流程終於走到最後了,看下最終的install操作的方法
下面兩個紅框可以看到,分別透過兩種不同的方式進行安裝,具體的判斷邏輯是根據包名來判斷的,如果存在包名則是覆蓋安裝,而不存在就是安裝一個新的apk。replacePackageLI()和installNewPackageLI()內部就和掃描系統中的package資訊一樣, 它把APK進行掃描,然後把apk中的資訊儲存到PackageManagerService中。瞭解4大元件的啟動過程就會知道,有一段流程是在PackageManagerService中獲取四大元件資訊,這些資訊就是透過把我們apk掃描安裝然後儲存到PackageMangerService中的。這樣我們的apk就已經安裝完成了。
圖中還有一個紅框,args.doRename()方法(這個args就是我們的FileInstallArgs),前面提到過我們的apk檔案會被複制到/data/app下,當複製進來的時候命名格式不是xx.apk,而這裡的doRename()方法就是把這個複製進來的檔案改名成XXXbase.apk。所以我們context.getPackageCodePath()獲取到的路徑就是改名後的資訊。
APK安裝的原始碼分析就分析到這,大致的流程就是獲取我們的安裝位置,然後複製我們的apk檔案到特定目錄,然後安裝我們的apk把apk的資訊儲存到PackageManagerService中。跟著上面的程式碼走一遍,相信還是很好理解的。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4606/viewspace-2806988/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 原始碼包安裝過程原始碼
- Android原始碼完全解析——View的Measure過程Android原始碼View
- Android View 原始碼解析(三) – View的繪製過程AndroidView原始碼
- Android 7.0/8.0 安裝APK時解析包錯誤問題AndroidAPK
- Linux原始碼包安裝過程及注意事項Linux原始碼
- android 反編譯APK取原始碼。Android編譯APK原始碼
- Oracle 18c rpm 安裝及解析安裝過程Oracle
- 從Chrome原始碼看DNS解析過程Chrome原始碼DNS
- 以太坊啟動過程原始碼解析原始碼
- SpringMVC原始碼解析(1)-啟動過程SpringMVC原始碼
- Dubbo服務呼叫過程原始碼解析④原始碼
- Dubbo原始碼解析之服務引入過程原始碼
- Dubbo原始碼解析之服務呼叫過程原始碼
- 看 Lumen 原始碼解析 Request 到 Response 過程原始碼
- Feign原始碼解析:初始化過程(一)原始碼
- Feign原始碼解析:初始化過程(二)原始碼
- Spark 原始碼系列(六)Shuffle 的過程解析Spark原始碼
- 【Android APK】解析SD卡上的APK檔案AndroidAPKSD卡
- Universal-Image-Loader原始碼解解析---display過程 + 獲取bitmap過程原始碼
- Dubbo原始碼解析之服務匯出過程原始碼
- Netty原始碼解析 -- 服務端啟動過程Netty原始碼服務端
- Netty原始碼解析 -- ChannelOutboundBuffer實現與Flush過程Netty原始碼
- vue原始碼解析-圖解diff詳細過程Vue原始碼圖解
- Spring Bean 的例項化過程原始碼解析SpringBean原始碼
- Android Retrofit原始碼解析Android原始碼
- Android原始碼解析-LiveDataAndroid原始碼LiveData
- Android setContentView原始碼解析AndroidView原始碼
- Android Handler 原始碼解析Android原始碼
- Android——LruCache原始碼解析Android原始碼
- React Native Android 原始碼分析之啟動過程React NativeAndroid原始碼
- Android系統原始碼分析--Activity啟動過程Android原始碼
- Android 原始碼分析(一)專案構建過程Android原始碼
- Fabric1.4原始碼解析:鏈碼例項化過程原始碼
- 關於Android安裝apk出現解析包異常問題情況總結AndroidAPK
- selenium安裝過程
- Netty原始碼解析 -- ChannelPipeline機制與讀寫過程Netty原始碼
- 從原始碼角度解析 Springboot 2.6.2 的啟動過程原始碼Spring Boot
- linux下通過原始碼安裝gitLinux原始碼Git