[轉(zhuǎn)] 一篇文章看明白 Android 從點擊應(yīng)用圖標(biāo)到界面顯示的過程 (遵循CC 4.0 BY-SA版權(quán)協(xié)議)

創(chuàng)新互聯(lián)是一家專業(yè)提供肥城企業(yè)網(wǎng)站建設(shè),專注與做網(wǎng)站、成都網(wǎng)站制作、HTML5建站、小程序制作等業(yè)務(wù)。10年已為肥城眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)絡(luò)公司優(yōu)惠進(jìn)行中。
從點擊桌面應(yīng)用圖標(biāo)到應(yīng)用顯示的過程我們再熟悉不過了,下面我們來分析下這個過程都做了什么。
本文主要對以下問題分析:
如不了解 Android 是如何從開機(jī)到 Launcher 啟動的過程,請先閱讀 Android - 系統(tǒng)啟動過程
我們知道 Android 系統(tǒng)啟動后已經(jīng)啟動了 Zygote,ServiceManager,SystemServer 等系統(tǒng)進(jìn)程;ServiceManager 進(jìn)程中完成了 Binder 初始化;SystemServer 進(jìn)程中 ActivityManagerService,WindowManagerService,PackageManagerService 等系統(tǒng)服務(wù)在 ServiceManager 中已經(jīng)注冊;最后啟動了 Launcher 桌面應(yīng)用。
其實 Launcher 本身就是一個應(yīng)用程序,運行在自己的進(jìn)程中,我們看到的桌面就是 Launcher 中的一個 Activity。
應(yīng)用安裝的時候,通過 PackageManagerService 解析 apk 的 AndroidManifest.xml 文件,提取出這個 apk 的信息寫入到 packages.xml 文件中,這些信息包括:權(quán)限、應(yīng)用包名、icon、apk 的安裝位置、版本、userID 等等。packages.xml 文件位于系統(tǒng)目錄下/data/system/packages.xml。
同時桌面 Launcher 會為安裝過的應(yīng)用生成不同的應(yīng)用入口,對應(yīng)桌面上的應(yīng)用圖標(biāo),下面分析點擊應(yīng)用圖標(biāo)的到應(yīng)用啟動的過程。
點擊 Launcher 中應(yīng)用圖標(biāo)將會執(zhí)行以下方法
在 system_server 進(jìn)程中的服務(wù)端 ActivityManagerService 收到 START_ACTIVITY_TRANSACTION 命令后進(jìn)行處理,調(diào)用 startActivity() 方法。
從 Launcher 點擊圖標(biāo),如果應(yīng)用沒有啟動過,則會 fork 一個新進(jìn)程。創(chuàng)建新進(jìn)程的時候,ActivityManagerService 會保存一個 ProcessRecord 信息,Activity 應(yīng)用程序中的AndroidManifest.xml 配置文件中,我們沒有指定 Application 標(biāo)簽的 process 屬性,系統(tǒng)就會默認(rèn)使用 package 的名稱。每一個應(yīng)用程序都有自己的 uid,因此,這里 uid + process 的組合就可以為每一個應(yīng)用程序創(chuàng)建一個 ProcessRecord。每次在新建新進(jìn)程前的時候會先判斷這個 ProcessRecord 是否已存在,如果已經(jīng)存在就不會新建進(jìn)程了,這就屬于應(yīng)用內(nèi)打開 Activity 的過程了。
進(jìn)程創(chuàng)建成功切換至 App 進(jìn)程,進(jìn)入 app 進(jìn)程后將 ActivityThread 類加載到新進(jìn)程,并調(diào)用 ActivityThread.main() 方法
此時只創(chuàng)建了應(yīng)用程序的 ActivityThread 和 ApplicationThread,和開啟了 Handler 消息循環(huán)機(jī)制,其他的都還未創(chuàng)建, ActivityThread.attach(false) 又會最終到 ActivityMangerService 的 attachApplication,這個工程其實是將本地的 ApplicationThread 傳遞到 ActivityMangerService。然后 ActivityMangerService 就可以通過 ApplicationThread 的代理 ApplicationThreadProxy 來調(diào)用應(yīng)用程序 ApplicationThread.bindApplication,通知應(yīng)用程序的 ApplicationThread 已和 ActivityMangerService 綁定,可以不借助其他進(jìn)程幫助直接通信了。此時 Launcher 的任務(wù)也算是完成了。
在 system_server 進(jìn)程中的服務(wù)端 ActivityManagerService 收到 ATTACH_APPLICATION_TRANSACTION 命令后進(jìn)行處理,調(diào)用 attachApplication()。
發(fā)送送完 SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION 命令,還會發(fā)送 BIND_APPLICATION_TRANSACTION 命令來創(chuàng)建 Application。
在 app 進(jìn)程中,收到 BIND_APPLICATION_TRANSACTION 命令后調(diào)用 ActivityThread.bindApplication()。
ApplicationThreadProxy.bindApplication(…) 會傳來這個應(yīng)用的一些信息,如ApplicationInfo,Configuration 等,在 ApplicationThread.bindApplication 里會待信息封裝成AppBindData,通過
將信息放到應(yīng)用里的消息隊列里,通過 Handler 消息機(jī)制,在 ActivityThread.handleMeaasge 里處理 H.BIND_APPLICATION 的信息,調(diào)用 AplicationThread.handleBindApplication。
Instrumentation:
這時 Application 就創(chuàng)建好了,這點很重要,很多資料里說 Application 是在performLaunchActivity() 里創(chuàng)建的,因為 performLaunchActivity() 也有mInstrumentation.newApplication 這個調(diào)用,newApplication() 函數(shù)中可看出會先判斷是否以及創(chuàng)建了 Application,如果之前已經(jīng)創(chuàng)建,就返回已創(chuàng)建的 Application 對象。
上面 fork 進(jìn)程時會發(fā)送 SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION 命令,在 app 進(jìn)程中,收到 SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION 命令后調(diào)用 ApplicationThread.scheduleLaunchActivity()。
與 Window 進(jìn)行關(guān)聯(lián),具體過程詳見: Activity,Window,View 之間的關(guān)系
Activity 的整體啟動流程如圖所示:
View顯示的關(guān)鍵,是我們?nèi)绾文玫紺anvas。Canvas是由Surface提供的,不同的Canvas實例,決定了顯示內(nèi)容使用軟件渲染(cpu)還是硬件渲染(gpu)。SurfaceFlinger則負(fù)責(zé)將不同Surface對應(yīng)的不同layer進(jìn)行圖層合并。
所有在同一個ViewGroup中的普通View,都會通過唯一的ViewRootImpl實例向同一個Surface實例獲取Canvas。SurfaceView具備獨立的Surface,該Surface對應(yīng)為SurfaceFlinger中獨立的layer。他們的顯示流程是不同的。
渲染,即生成RGB、YUV等顯示器可顯示數(shù)據(jù)的過程。比如上層通過Canvas畫一個矩形,最終需要生成一幀數(shù)據(jù);給輸入視頻加特效;輸入的是YUV,希望轉(zhuǎn)為RGB顯示;甚至輸入的就是YUV,但與顯示需要的分辨率不一致。這些場景,都需要將渲染后得到的數(shù)據(jù)放入Surface的顯示Buffer中。
多個layer合成,可以通過GLES合成(也叫Client合成或GPU合成),也可以直接通過HWC進(jìn)行硬件合成(也叫Device合成)。
什么是息屏顯示?
息屏顯示就是手機(jī)在息屏狀態(tài)下,屏幕上會顯示當(dāng)前時間、日期信息,無需點亮手機(jī)屏幕即可查看。息屏顯示的原理主要是利用了OLED屏幕像素點自發(fā)光的特性,僅顯示時間的像素點發(fā)光,功耗相比LCD屏幕要低很多。
玩過Android源碼的同學(xué)應(yīng)該知道,在Settings里有一個開關(guān)項:
既然知道主動顯示開關(guān)是放在設(shè)置里面的,那不妨先從Settings的源碼看起,首先找到主動顯示對應(yīng)的Preference,
然后發(fā)現(xiàn)在AmbientDisplaySettings里注冊了一些controller,
先關(guān)注里面的兩個:AmbientDisplayNotificationsPreferenceController和AmbientDisplayAlwaysOnPreferenceController,看名字大概能知道,第一個與通知有關(guān),應(yīng)該是上文提到的息屏后來通知才顯示;而第二個就是我們要找的“始終開啟”。
AmbientDisplayAlwaysOnPreferenceController :
分析AmbientDisplayAlwaysOnPreferenceController的源碼發(fā)現(xiàn),AlwaysOn的enable和available狀態(tài)都需要通過AmbientDisplayConfiguration 這個類來獲得,并且這個類位于framework中。
簡單介紹下AmbientDisplayConfiguration 中與alwaysOn有關(guān)的幾個函數(shù):
alwaysOnAvailable 為true需要同時滿足兩個條件:
alwaysOnEnabled 為true需要同時滿足三個條件:
原來源碼里面默認(rèn)把AlwaysOn功能給關(guān)閉了,如果想啟用這個功能,需要修改config.xml里的兩個值或者強(qiáng)制alwaysOnAvailable返回true,修改后設(shè)置里的主動顯示一欄就會多出一項“始終開啟”可以勾選,這樣一來我們的設(shè)備在息屏之后就能自動開啟主動顯示功能了。
以上源碼均取自Android O
當(dāng)前名稱:android顯示,android顯示文本內(nèi)容
分享地址:http://chinadenli.net/article11/dseicgd.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供Google、靜態(tài)網(wǎng)站、品牌網(wǎng)站建設(shè)、ChatGPT、App設(shè)計、用戶體驗
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)