浅析调用android的content provider(一)
- 概述
- 應用進程的管理模型
?? ? ??Android框架內,應用程序Java代碼的入口為ActivityThread.main。用來管理不同的應用的服務名稱為activity。它的模型大致為:
?? ? ??左邊為多個應用進程,每個進程中有個主線程ActivityThread.main,Looper.loop()是主線程的消息循環。所有的應用進程都是通過IBinder機制和ActivityManagerService進程進行交互的。應用進程為了能調用activity服務進程的ActivityManagerService中的方法,必須通過ActivityManagerProxy類。activity服務進程則通過ApplicationThreadProxy類與服務進程的ApplicationThread通信。ApplicationThread的作用主要是將activity服務進程的調用轉換為ActivityThread主線程中的消息,從而保證ActivityManagerService的調用是異步的。
?? ? ??右邊的activity服務進程是所有應用的服務進程,用于管理應用進程。啟動新的應用進程時,會向zygote服務進程發送socket消息。zygote接收到消息后,則會啟動新的delvik虛擬機,然后運行ActivityThread.main,啟動新的應用。
- PackageManagerService
?? ? ??PackageManagerService也是一個服務,是用來管理手機內所有的apk包的。調用它的方式和調用ActivityManagerService是一樣的,通過IBinder。它的初始化入口為PackageManagerService.main:
?? ? ??main方法主要是創建一個PackageManagerService,然后注冊到ServiceManager中,名稱為"package”。PackageManagerService的構造函數中,會去查找系統目錄和應用目錄下的apk文件,以獲取應用的包相關的信息;比如:包名稱,包含的Acvity、Provider等。
[java]?view plaincopy
?? ? ??scanDirLI函數中,對于每個package,使用函數scanPackageLI解析其中的信息(此處應該是讀取AndroidManifest.xml)。scanPackageLI檢查相關信息后,又會調用另一個scanPackageLI。這個函數內部會掃描到手機內所有的Provider信息:
[java]?view plaincopy
?? ? ??mProvidersByComponent保存了所有的provider信息,這部分數據源自于manifest。每個數據包含了PackageParser.Provider、包名稱和Provider的類名。
?? ? ??到這里,我們可以看到,PackageManagerService真的是用來管理手機的應用包的。通過它可以知道所有的系統可用資源。當然這些資源只是一些靜態信息。通過這些信息,可以創建應用進程、初始化相關的Android組件。
- 應用進程的初始化
[java]?view plaincopy
?? ? ??attach函數中,回去調用ActivityManagerService.attachApplication方法。
[java]?view plaincopy
?? ? ??此時,會進入ActivityManagerService的進程空間,進入方法attachApplicationLocked,它會去獲取和當前客戶端應用程序關聯的Provider信息。
[java]?view plaincopy
?? ? ??根據上面的信息,很容易知道此處是通過PackageManagerService獲取Provider信息的。參數app表明,只是取運行在該app內的Provider。根據Android的文檔,content provider必須在對應的AndroidManifest.xml中定義。默認情況下,是運行在安裝包名稱命名的進程里面。你也可以在android:process屬性中制定所屬的進程名稱。另一個重要的屬性android:multiprocess則可以指定provider的初始化方式,是分散在調用端進程中,從而避免進程間通信;還是只初始化在某個進程內,各個調用端只保留provider的代理。
?? ? ??隨后,通過下面的方法調用,返回到應用程序的進程空間,參數中包含了上面獲得的providers。此處的thread實際上就是應用端的ApplicationThread對象。
?? ? ??ApplicationThread.bindApplication會發送BIND_APPLICATION消息給主線程。主線程會調用ActivityThread.handleBindApplication方法。這個函數里面主要分兩步:一是根據需要創建Application、ApplicationContext和ApplicationContentResolver對象。因為,有可能多個apk運行在一個進程中,那么它們內部的組件(Component)執行的上下文(context)是不一樣的。這幾個對象實際上就是provider執行的上下文。二是根據傳遞過來的provider信息,創建provider實例,并保存在ActivityThread.mProviderMap中。具體的實例化provider過程如下(下面的代碼位于ActivityThread.handleBindApplication中):
[java]?view plaincopy
?? ? ??獲取ActivityManagerService傳遞過來的provider信息,并在本進程中初始化。具體的,installContentProviders方法中,會對每個provider調用installProvider方法:
[java]?view plaincopy
?? ? ??installProvider方法中,主要是實例化Provider,并保存到mProviderMap中:
[java]?view plaincopy
?? ? ??ActivityManagerService.publishContentProviders的實現也很簡單,主要是將provider信息保存到ActivityManagerService.mProvidersByName中。具體參見源碼。
- 總結
?? ? ??下一篇文章會介紹調用provider的流程。
轉載于:https://www.cnblogs.com/zsw-1993/p/4879932.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的浅析调用android的content provider(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android11代码关机
- 下一篇: 基于Matlab的同态滤波彩色图像增强算