Android應用程序安裝與Launcher啟動機制


 

以下資料摘錄整理自老羅的Android之旅博客,是對老羅的博客關於Android底層原理的一個抽象的知識概括總結(如有錯誤歡迎指出)(侵刪):
http://blog.csdn.net/luoshengyang/article/details/8923485
http://blog.csdn.net/luoshengyang/article/details/12957169

整理by Doing

 
            Android系統在啟動的過程中,會啟動一個應用程序管理服務PackageManagerService,這個服務負責掃描系統中特定的目錄,找到里面的應用程序文件,即以Apk為后綴的文件,然后對這些文件進解析(其實 就是 解析應用程序配置文件AndroidManifest.xml 的過程,並從里面得到得到應用程序的相關信息,例如得到應用程序的組件Activity、Service、Broadcast Receiver和Content Provider等信息 ),得到應用程序的相關信息, 完成應用程序的安裝 過程。
          通過 ActivityManagerService 這個服務, 我們就可以在系統中正常地 使用這些應用程序 了。
 
  • PackageManagerService負責安裝系統的應用程序:
  1.  Android系統在啟動的過程中,Zygote進程啟動SystemServer組件SystemServer組件啟動PackageManagerService服務、ActivityManagerService服務等
  2. PackageManagerService服務啟動過程創建了一個PackageManagerService服務實例把這個服務添加到ServiceManager中去ServiceManager是Android系統Binder進程間通信機制的守護進程,負責管理系統中的Binder對象)。
  3. PackageManagerService類的構造函數中開始執行安裝應用程序的過程調用scanDirLI函數來掃描移動設備上的五個目錄中的Apk文件( /system/framework、 /system/app、 /vendor/app、/data/app、 /data/app-private對於目錄中的每一個文件,如果是以Apk作為后綴名,那么就調用scanPackageLI函數來對它進行解析和安裝
  4. 首先會為這個Apk文件創建一個PackageParser實例,接着調用這個實例的parsePackage函數來對這個Apk文件進行解析(這個函數最后還會調用另外一個版本的scanPackageLI函數把來解析后得到的應用程序信息保存在PackageManagerService中。見后):
  5. 每一個Apk文件都是一個歸檔文件,它里面包含了Android應用程序的配置文件AndroidManifest.xml,這里主要就是要對這個配置文件解析就行了。從Apk歸檔文件中得到這個配置文件后,就調用另一外版本的parsePackage函數對這個應用程序進行解析:對AndroidManifest.xml文件中的各個標簽進行解析,如application標簽的解析,這是通過調用parseApplication函數來進行的。
  6. 解析完成后,一層層返回,調用另一個版本的scanPackageLI函數,把前面解析應用程序得到的package、provider、service、receiver和activity等信息保存在PackageManagerService服務中(保存在mPackages、mActivities、mReceivers、mServices等成員變量(HashMap類型)中)
 
 
  •         這些應用程序只是相當於在PackageManagerService服務注冊好了,如果我們想要在Android桌面上看到這些應用程序,還需要有一個Home應用程序(Android系統默認的Home應用程序就是Launcher),負責從PackageManagerService服務中把這些安裝好的應用程序取出來,並以友好的方式在桌面上展現出來,例如以快捷圖標的形式:
  1. 系統中的應用程序安裝好了以后,SystemServer組件接下來通過ActivityManagerService啟動Home應用程序Launcher
  2. ActivityManagerService.startHomeActivityLocked() 創建一個CATEGORY_HOME類型的Intent,然后通過Intent.resolveActivityInfo函數向PackageManagerService查詢Category類型為HOME的Activity
  3. 由於是第一次啟動這個Activity,接下來調用函數getProcessRecordLocked返回來的ProcessRecord值為null,於是調用mMainStack.startActivityLocked函數啟動com.android.launcher2.Launcher這個Activity,接着調用它的onCreate函數
  4. 把加載應用程序的操作為一個消息來處理:sWorker(Handler)通過它的post方式把一個消息放在消息隊列中去,然后系統就會調用傳進去的參數mLoaderTask(LoaderTask類型)的run函數來處理這個消息:調用loadAndBindAllApps成員函數,由於還沒有加載過應用程序,這里的mAllAppsLoaded為false,於是調用loadAllAppsByBatch,構造一個CATEGORY_LAUNCHER類型的Intent,mContext.getPackageManager()獲得PackageManagerService的接口,通過這個PackageManagerService.queryIntentActivities接口來取回所有Action類型為Intent.ACTION_MAIN,並且Category類型為Intent.CATEGORY_LAUNCHER的Activity(前面啟動PackageManagerService時,會把系統中的應用程序都解析一遍,然后把解析得到的Activity都保存在mActivities成員變量中,這里通過這個mActivities變量的queryIntent函數返回符合條件intent的Activity,這里要返回的便是Action類型為Intent.ACTION_MAIN,並且Category類型為Intent.CATEGORY_LAUNCHER的Activity)
  5. Launcher.bindAllApplications調用AllApps2D.setAppssetApps調用addApps函數來為上一步得到的每一個應用程序創建一個ApplicationInfo實例了,有了這些ApplicationInfo實例之后,就可以在桌面上展示系統中所有的應用程序了。到了這里,系統默認的Home應用程序Launcher就把PackageManagerService中的應用程序加載進來了:當我們點擊Home按鍵時,便會響應Launcher.onClick函數調用showAllApps函數顯示應用程序圖標把剛才加載好的應用程序以圖標的形式展示出來了。
  6. 點擊這些應用程序圖標時,便會響應AllApps2D.onItemClick函數,然后調用Launcher.startActivitySafely函數來啟動應用程序
 
 
 




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM