注:
原文來(lái)自我的CSDN博客:http://blog.csdn.net/foreverJQQ/article/details/76268404
Android 系統(tǒng) SystemUI 介紹
Android 的 SystemUI 其實(shí)就是 Android 的系統(tǒng)界面,它包括了界面上方的狀態(tài)欄 status bar,下方的導(dǎo)航欄Navigation Bar,鎖屏界面 Keyguard ,電源界面 PowerUI,近期任務(wù)界面 Recent Task 等等。對(duì)于用戶而言,SystemUI 的改動(dòng)是最能直觀感受到的。因此,每個(gè) Android 版本在 SystemUI 上都有比較大的改動(dòng)。而對(duì)開發(fā)者而言,理解 Android SystemUI 對(duì)優(yōu)化Android系統(tǒng)界面,改善用戶體驗(yàn)十分重要。
SystemUI 在哪
在 Andorid 系統(tǒng)源碼中,package/apps下放的是系統(tǒng)內(nèi)置的一些 app,例如 settings,camera,Phone,Message 等等。而在 Framework/base/package 下,它們也是系統(tǒng)的 app,SystemUI 就在此目錄下。它控制著整個(gè)Android系統(tǒng)的界面,但其實(shí)他也是一個(gè) app,不同于一般的 app,它不可卸載也不可以被第三方應(yīng)用替換。
SystemUI 整體結(jié)構(gòu)
這是 SystemUI 相關(guān)類的繼承關(guān)系圖,可以看到 SystemUI 為基類,每個(gè)子類實(shí)現(xiàn)了不同的系統(tǒng)界面。
- Status Bar 系統(tǒng)上方的狀態(tài)欄
- Navigator Bar 系統(tǒng)下方的導(dǎo)航欄
- Keyguard 鎖屏界面
- PowerUI 電源界面
- Recents Screen 近期任務(wù)界面
- VolumeUI 音量調(diào)節(jié)對(duì)話框
- Stack Divider 分屏功能調(diào)節(jié)器
- PipUI 畫中畫界面
- Screenshot 截屏界面
- RingtonePlayer 鈴聲播放器界面
- Settings Activity 系統(tǒng)設(shè)置中用到的一些界面,例如:NetworkOverLimitActivity,UsbDebuggingActivity等。
SystemUI的啟動(dòng)流程
先找到 framework/base/service/java/com/android/server/SystemServer.java 文件,里面有個(gè)main()方法,main 方法如下:
public static void main(String[] args){
new SystemServer().run()
}
main 方法里啟動(dòng)了 run() 方法,而在 run 方法中調(diào)用了 startBootstrapServices() 方法和 startOtherServices() 方法,在 startOtherServices() 里 mActivityManagerService.systemReady 創(chuàng)建線程去執(zhí)行startSystemUi(context),這里將啟動(dòng) SystemUI。具體方法如下:
然后我們進(jìn)入設(shè)置啟動(dòng) systemui 程序的 SystemUIService 文件里,該文件在framework/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java.我們看該文件的onCreate() 方法。方法如下:
可以看到有一句 ((SystemUIApplication) getApplication()).startServicesIfNeeded(),這句很關(guān)鍵,我們?cè)龠M(jìn)入 startServicesIfNeeded(),看看具體是如何啟動(dòng)系統(tǒng)服務(wù)的。該方法如下:
其中有一個(gè) for 循環(huán),循環(huán)里第一句就是將 service[i] 賦值給 cl, 那么service里存的是什么呢?找到 service[i] 的賦值如下:
看到這里我們就明白了,這里是拿到每個(gè)和 SystemUI 相關(guān)的類的反射,存到了 service[] 里,然后賦值給cl,緊接著將通過(guò)反射將其轉(zhuǎn)化為具體類的對(duì)象,存到了mService[i]數(shù)組里,最后對(duì)象調(diào) start() 方法啟動(dòng)相關(guān)類的服務(wù),啟動(dòng)完成后,回調(diào) onBootCompleted( ) 方法。
mService[i] 里的值不同時(shí),調(diào)用的 start() 方法也不相同,這里我們以S ystemBars 的 start() 為例,所以mService[i].start() 先認(rèn)為是 SystemBars.start().
SystemBars.java 位于framework/base/packages/SystemUI/res/com/android/systemui/statusbar/SystemBars.java ,找到 start() 方法:
這里調(diào)用了 mServiceMonitor.start(),旁邊注釋說(shuō)的很清楚如果服務(wù)沒有啟動(dòng)的話就調(diào)用onNoService()方法,進(jìn)入 onNoService() 方法,該方法就位于 start() 方法下方,可以看到方法中調(diào)用了CreateStatusBarFromConfig() 該方法如下:
從中可以知道,該方法中先讀取 value/config.xml 文件中 config_statusBarComponent 的值,這里為:com.android.systemui.statusbar.phone.PhoneStatusBar,然后通過(guò)反射得到了 PhoneStatusBar 對(duì)象,最后的 mStartus.start() 也就等于 PhoneStatusBar.start(),進(jìn)入該方法,會(huì)發(fā)現(xiàn),里面調(diào)用了super.start(),也就是先執(zhí)行了父類的 start() ,其父類為 BaseStatusBar,該類的star()方法較多,就不放出來(lái)了,我們看重點(diǎn),找到里面有調(diào)用一個(gè) createAndAddWindows(),該方法為抽象方法,則會(huì)調(diào)用它的子類的方法,這里也就是 PhoneStatusBar 的 createAndAddWindows()方法,如下:
createAndAddWindows() 里只調(diào)用了 addStaBarWindow() 方法,而在該方法里,調(diào)用了makeStartusBarView,看名字就知道該方法關(guān)鍵,意為構(gòu)建statusBar視圖。該方法很長(zhǎng),里面有inflateStatusBarWindow(),進(jìn)入該方法,可以看到,這么一句:
然后,我們通過(guò) super_status_bar.xml 的分析 SystemBars 的大致視圖構(gòu)成了,super_status_bar.xml 代碼如下:
super_status_bar.xml
super_status_bar.xml 中 include 了一個(gè)名稱為 status_bar 的布局文件
super_status_bar.xml*中 include 了一個(gè)名稱為 status_bar_expanded 的布局文件
這里的 status_bar 便是系統(tǒng)狀態(tài)欄的布局文件,status_bar_expanded 便是下拉的通知窗口的布局文件
上述 super_status_bar.xml 與如下視圖對(duì)應(yīng):
PhoneStatusBarView 即為手機(jī)最上方的狀態(tài)欄,主要用于顯示系統(tǒng)狀態(tài),通知等,主要包括 notification icons 和 status bar icons。status_bar.xml 即對(duì)應(yīng)狀態(tài)欄的視圖如下:
PanelHolder
PanelHolder是用戶下拉 status bar 后得到的 view。它主要包含 QuickSettings 和 Notification panel 兩個(gè)部分。
PanelHolder是一個(gè)繼承自 FrameLayout的自定義 view,它的內(nèi)容是通過(guò) include status_bar_expanded.xml進(jìn)行填充的。
PanelHolder的布局比較復(fù)雜,為了提高 view 的重用性大量的使用了 include 標(biāo)簽。
status_bar_expanded.xml 對(duì)應(yīng)的視圖:
KeyguardBouncer
KeyguardBouncer是鎖屏解鎖界面,根據(jù)用戶設(shè)置的解鎖方式不同,展示不同的解鎖模式。
keyguard_bouncer.xml 對(duì)應(yīng)的 KerguardBouncer 視圖:
附:
SystemUI啟動(dòng)流程圖:
參考文章:
http://www.itdecent.cn/p/0ab1279465fa
http://qiangbo.space/2017-05-09/AndroidAnatomy_SystemUI_Intro/
http://qiangbo.space/2017-06-04/AndroidAnatomy_SystemUI_Bar/
http://www.open-open.com/lib/view/open1494316049681.html