注:
原文來自我的CSDN博客:http://blog.csdn.net/foreverJQQ/article/details/76268404
Android 系統 SystemUI 介紹
Android 的 SystemUI 其實就是 Android 的系統界面,它包括了界面上方的狀態(tài)欄 status bar焕参,下方的導航欄Navigation Bar霞势,鎖屏界面 Keyguard ,電源界面 PowerUI泞坦,近期任務界面 Recent Task 等等窖贤。對于用戶而言,SystemUI 的改動是最能直觀感受到的贰锁。因此赃梧,每個 Android 版本在 SystemUI 上都有比較大的改動。而對開發(fā)者而言豌熄,理解 Android SystemUI 對優(yōu)化Android系統界面授嘀,改善用戶體驗十分重要。
SystemUI 在哪
在 Andorid 系統源碼中锣险,package/apps下放的是系統內置的一些 app蹄皱,例如 settings,camera芯肤,Phone巷折,Message 等等。而在 Framework/base/package 下崖咨,它們也是系統的 app锻拘,SystemUI 就在此目錄下。它控制著整個Android系統的界面掩幢,但其實他也是一個 app逊拍,不同于一般的 app上鞠,它不可卸載也不可以被第三方應用替換。
SystemUI 整體結構
這是 SystemUI 相關類的繼承關系圖芯丧,可以看到 SystemUI 為基類芍阎,每個子類實現了不同的系統界面。
- Status Bar 系統上方的狀態(tài)欄
- Navigator Bar 系統下方的導航欄
- Keyguard 鎖屏界面
- PowerUI 電源界面
- Recents Screen 近期任務界面
- VolumeUI 音量調節(jié)對話框
- Stack Divider 分屏功能調節(jié)器
- PipUI 畫中畫界面
- Screenshot 截屏界面
- RingtonePlayer 鈴聲播放器界面
- Settings Activity 系統設置中用到的一些界面缨恒,例如:NetworkOverLimitActivity谴咸,UsbDebuggingActivity等。
SystemUI的啟動流程
先找到 framework/base/service/java/com/android/server/SystemServer.java 文件骗露,里面有個main()方法岭佳,main 方法如下:
public static void main(String[] args){
new SystemServer().run()
}
main 方法里啟動了 run() 方法,而在 run 方法中調用了 startBootstrapServices() 方法和 startOtherServices() 方法萧锉,在 startOtherServices() 里 mActivityManagerService.systemReady 創(chuàng)建線程去執(zhí)行startSystemUi(context)珊随,這里將啟動 SystemUI。具體方法如下:
然后我們進入設置啟動 systemui 程序的 SystemUIService 文件里柿隙,該文件在framework/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java.我們看該文件的onCreate() 方法叶洞。方法如下:
可以看到有一句 ((SystemUIApplication) getApplication()).startServicesIfNeeded(),這句很關鍵禀崖,我們再進入 startServicesIfNeeded()衩辟,看看具體是如何啟動系統服務的。該方法如下:
其中有一個 for 循環(huán)波附,循環(huán)里第一句就是將 service[i] 賦值給 cl艺晴, 那么service里存的是什么呢?找到 service[i] 的賦值如下:
看到這里我們就明白了掸屡,這里是拿到每個和 SystemUI 相關的類的反射封寞,存到了 service[] 里,然后賦值給cl折晦,緊接著將通過反射將其轉化為具體類的對象钥星,存到了mService[i]數組里,最后對象調 start() 方法啟動相關類的服務满着,啟動完成后,回調 onBootCompleted( ) 方法贯莺。
mService[i] 里的值不同時风喇,調用的 start() 方法也不相同,這里我們以S ystemBars 的 start() 為例缕探,所以mService[i].start() 先認為是 SystemBars.start().
SystemBars.java 位于framework/base/packages/SystemUI/res/com/android/systemui/statusbar/SystemBars.java 魂莫,找到 start() 方法:
這里調用了 mServiceMonitor.start(),旁邊注釋說的很清楚如果服務沒有啟動的話就調用onNoService()方法爹耗,進入 onNoService() 方法耙考,該方法就位于 start() 方法下方谜喊,可以看到方法中調用了CreateStatusBarFromConfig() 該方法如下:
從中可以知道,該方法中先讀取 value/config.xml 文件中 config_statusBarComponent 的值,這里為:com.android.systemui.statusbar.phone.PhoneStatusBar倦始,然后通過反射得到了 PhoneStatusBar 對象斗遏,最后的 mStartus.start() 也就等于 PhoneStatusBar.start(),進入該方法鞋邑,會發(fā)現诵次,里面調用了super.start(),也就是先執(zhí)行了父類的 start() ,其父類為 BaseStatusBar枚碗,該類的star()方法較多逾一,就不放出來了,我們看重點肮雨,找到里面有調用一個 createAndAddWindows()遵堵,該方法為抽象方法,則會調用它的子類的方法怨规,這里也就是 PhoneStatusBar 的 createAndAddWindows()方法陌宿,如下:
createAndAddWindows() 里只調用了 addStaBarWindow() 方法,而在該方法里椅亚,調用了makeStartusBarView限番,看名字就知道該方法關鍵,意為構建statusBar視圖呀舔。該方法很長弥虐,里面有inflateStatusBarWindow(),進入該方法媚赖,可以看到霜瘪,這么一句:
然后,我們通過 super_status_bar.xml 的分析 SystemBars 的大致視圖構成了惧磺,super_status_bar.xml 代碼如下:
super_status_bar.xml
super_status_bar.xml 中 include 了一個名稱為 status_bar 的布局文件
super_status_bar.xml*中 include 了一個名稱為 status_bar_expanded 的布局文件
這里的 status_bar 便是系統狀態(tài)欄的布局文件颖对,status_bar_expanded 便是下拉的通知窗口的布局文件
上述 super_status_bar.xml 與如下視圖對應:
PhoneStatusBarView 即為手機最上方的狀態(tài)欄,主要用于顯示系統狀態(tài)磨隘,通知等缤底,主要包括 notification icons 和 status bar icons。status_bar.xml 即對應狀態(tài)欄的視圖如下:
PanelHolder
PanelHolder是用戶下拉 status bar 后得到的 view番捂。它主要包含 QuickSettings 和 Notification panel 兩個部分个唧。
PanelHolder是一個繼承自 FrameLayout的自定義 view,它的內容是通過 include status_bar_expanded.xml進行填充的。
PanelHolder的布局比較復雜设预,為了提高 view 的重用性大量的使用了 include 標簽徙歼。
status_bar_expanded.xml 對應的視圖:
KeyguardBouncer
KeyguardBouncer是鎖屏解鎖界面,根據用戶設置的解鎖方式不同,展示不同的解鎖模式魄梯。
keyguard_bouncer.xml 對應的 KerguardBouncer 視圖:
附:
SystemUI啟動流程圖:
參考文章:
http://www.reibang.com/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