systemUI之statusbar

看标题应该能猜出来这会是一个系列,不管写的咋样,就当是小结吧。因为是第一篇,所以会先说下systemUI是嘛,然后从view的角度认识一下systemUI的各个部件,重点分析一下statusbar的布局结构;最后是statusbar的加载流程。

一,文件目录

systemUI相对锁屏什么的它算是很规矩了,标准的android工程,安静的待在:

.\frameworks\base\packages\SystemUI目录下,可以直接单编译成apk,注意要push到system/app下面重启验证效果。

二,视图部件

上面的图简单的表示了systemUI的结构,其实这个从我们的代码目录也可以知道个大概,那么啥是systemUI,干嘛独独要把这些放在一起弄个番号呢?个人本着细心学习,大胆推测的精神得到以下证据:1,它们都非常勤快,至少都是赶在launcher前面打卡;2不知疲倦,常驻内存,随时可以响应用户的使唤.有这些共性说它们是一奶同胞也就有论据了,如果你够耐心看下去会发现确实都是由一个systemUI服务孵化的。

因为该文的主角是statusbar,所以我们多花些笔墨解析一下它。statusbar在手机上其实分两个view:StatusBar和StatusBarExpanded,就拿StatusBar作典型进行分析吧:

从上面的层次图可以看出icon和ticker是两个平行frameLayout,一般时候都是icon布局显示,当有notification进来时ticker显示,为了方便研究分别给它们加了background color:

三,statusbar启动流程

我们知道了statusbar是啥,混了个脸熟后就可以对它的生平以及来龙去脉考究一番。为了描述方便,我试着把一个连贯的过程分成以下四步:

1,  systemUI是个服务

看一个android工程我们都会从AndroidManifest.xml文件开始分析,这个也不例外。从manifest文件中我们找到SystemUIService这个重要的服务,整个systemUI就是由它而起。通过简单的find命令,在systemserver.java里面找到了SystemUIService的启动代码。

2,  systemServer相关

systemServer的水其实非常深,它起于Zygote,负责Android系统所有的service注册登记,生和死。系统的分析需要另起篇幅,这里我们使用查找直接找到systemUIService的启动代码:

3,  systemUIservice

接上面,我们直接看onCreate方法,主要作用就是根据机器硬件配置决定是实例化statusbar还是systembar。并启动相应的start方法。

public void onCreate() {// Pick status bar or system bar.//1.aidl远程调用windowmanager实例IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));try {//2.在PhoneWindowManager里面进行判定是phone还是tablet或其他。SERVICES[0] = wm.canStatusBarHide()? R.string.config_statusBarComponent: R.string.config_systemBarComponent;} catch (RemoteException e) {Slog.w(TAG, "Failing checking whether status bar can hide", e);}//3.实例化statusbar。final int N = SERVICES.length;mServices = new SystemUI[N];for (int i=0; i<N; i++) {Class cl = chooseClass(SERVICES[i]);Slog.d(TAG, "loading: " + cl);try {mServices[i] = (SystemUI)cl.newInstance();} catch (IllegalAccessException ex) {throw new RuntimeException(ex);} catch (InstantiationException ex) {throw new RuntimeException(ex);}//4.启动statusbar。mServices[i].mContext = this;Slog.d(TAG, "running: " + mServices[i]);mServices[i].start();}}

通过查看systemUI的资源文件找到以下定义

<!-- Component to be usedas the status bar service.  Mustimplement the IStatusBarinterface. This name is in the ComponentName flattened format (package/class)  --><string name="config_statusBarComponent"translatable="false">com.android.systemui.statusbar.phone.PhoneStatusBar</string><!--Component to be used as the system bar service. Must implement the IStatusBarinterface. This name is in the ComponentName flattened format (package/class)  -->
<string name="config_systemBarComponent" translatable="false">com.android.systemui.statusbar.tablet.TabletStatusBar</string>

所以实际上起的是PhoneStatusBar.java的start()。

4,PhoneStatusBar

前面的都是铺垫,到这里终于要来实际的了。分析的顺序是PhoneStatusBar.start() => StatusBar.start()=>PhoneStatusBar.makeStatusBarView()。

public void start() {mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();mWindowManager = IWindowManager.Stub.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
//调用父类statusBar的start方法。super.start();
//加载导航条。addNavigationBar();//addIntruderView();// 最后调用policy加载更新图标mIconPolicy = new PhoneStatusBarPolicy(mContext);
}

我们进入statusBar.start()一探究竟:

public void start(){// 1.First set up our views and stuff.View sb = makeStatusBarView();// 2.Connect in to the status bar manager service。。。。。。try {mBarService.registerStatusBar(mCommandQueue, iconList,notificationKeys, notifications,switches, binders);} catch (RemoteException ex) {// 3.If the system process isn't there we're doomed anyway.}disable(switches[0]);setSystemUiVisibility(switches[1]);topAppWindowChanged(switches[2] != 0);// 4.StatusBarManagerService has a back up of IME token and it's restoredhere.setImeWindowStatus(binders.get(0),switches[3], switches[4]);setHardKeyboardStatus(switches[5] != 0,switches[6] != 0);// 5.Set up the initial icon stateint N = iconList.size();int viewIndex = 0;for (int i=0; i<N; i++) {StatusBarIcon icon =iconList.getIcon(i);if (icon != null) {addIcon(iconList.getSlot(i), i,viewIndex, icon);viewIndex++;}}// 6.Set up the initial notification stateN = notificationKeys.size();if (N == notifications.size()) {for (int i=0; i<N; i++) {addNotification(notificationKeys.get(i), notifications.get(i));}} else {Log.wtf(TAG, "Notification list length mismatch: keys=" + N+ " notifications=" +notifications.size());}// 7.Put up the viewfinal int height = getStatusBarHeight();final WindowManager.LayoutParams lp = newWindowManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,height,WindowManager.LayoutParams.TYPE_STATUS_BAR,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING|WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,PixelFormat.OPAQUE);// 8.the status bar should be in an overlay if possiblefinal Display defaultDisplay= ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();if (ActivityManager.isHighEndGfx(defaultDisplay)){lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;}lp.gravity = getStatusBarGravity();lp.setTitle("StatusBar");lp.packageName = mContext.getPackageName();lp.windowAnimations = R.style.Animation_StatusBar;WindowManagerImpl.getDefault().addView(sb,lp);if (SPEW) {Slog.d(TAG, "Added status bar view: gravity=0x" + Integer.toHexString(lp.gravity)+ " icons=" + iconList.size()+ " disabled=0x" + Integer.toHexString(switches[0])+ " lights=" + switches[1]+ " menu=" + switches[2]+ " imeButton=" + switches[3]);}mDoNotDisturb = new DoNotDisturb(mContext);
}

statusBar乃至整个systemUI的view是怎么创建起来的,我们必须进入第一步的makeStatusBarView()方法细看一下。

protected View makeStatusBarView() {。。。。
//1.加载ExpandedView。ExpandedView expanded = (ExpandedView)View.inflate(context,R.layout.status_bar_expanded, null);if (DEBUG) {expanded.setBackgroundColor(0x6000FF80);}expanded.mService = this;
//2.加载PhoneStatusBarView。PhoneStatusBarView sb = (PhoneStatusBarView)View.inflate(context,R.layout.status_bar, null);sb.mService = this;mStatusBarView = sb;
//3.决定是否加载NavigationBarView。try {boolean showNav = mWindowManager.hasNavigationBar();if (showNav) {mNavigationBarView = (NavigationBarView) View.inflate(context, R.layout.navigation_bar, null);mNavigationBarView.setDisabledFlags(mDisabled);}} catch (RemoteException ex) {// no window manager? good luck with that}
//4.加载statusBar的各个具体控件。// figure out which pixel-format to use for the status bar.mPixelFormat = PixelFormat.OPAQUE;mStatusIcons = (LinearLayout)sb.findViewById(R.id.statusIcons);mNotificationIcons = (IconMerger)sb.findViewById(R.id.notificationIcons);mIcons = (LinearLayout)sb.findViewById(R.id.icons);mTickerView = sb.findViewById(R.id.ticker);
//4.实例化各种控制器。mLocationController = new LocationController(mContext); // will post a notificationmBatteryController = new BatteryController(mContext);mBatteryController.addIconView((ImageView)sb.findViewById(R.id.battery));mNetworkController = new NetworkController(mContext);
//5.加载并更新RecentsPanelView。// RecentsPanelmRecentTasksLoader = new RecentTasksLoader(context);updateRecentsPanel();
//6.注册定制的监听器。// receive broadcastsIntentFilter filter = new IntentFilter();filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);filter.addAction(Intent.ACTION_SCREEN_OFF);context.registerReceiver(mBroadcastReceiver, filter);return sb;}

以上大概就是就是整个systemUI的加载流程,主线就是statusBar,在加载它的时候顺便也把RecentsPanel,NavigationBarView等看起来没啥联系的东西也一块加载好,私以为这里的代码结构还可以更好,4.1可能会有所改善吧。

小结:

这些东西其实一个月前就想写了,断断续续的一直没有开始着手,一来总有很多琐事或看起来更重要的事来打扰,二来是总觉得自己看的肤浅,不敢写,也不想写。不过总算是写出第一篇了。systemUI这块是整个系统UI风格的关键也最大程度地影响着用户的日常体验,无论是优化还是现有的usb处理挂载流程都有很多东西值得去挖掘,日后陆续放出吧。

systemUI之statusBar相关推荐

  1. Android 4.0 ICS SystemUI浅析——StatusBar加载流程分析

    前面两篇文章< Android 4.0 ICS SystemUI浅析--SystemUI启动流程>.< Android 4.0 ICS SystemUI浅析--StatusBar结构 ...

  2. Android SystemUI之StatusBar,状态栏(二)

    Android  SystemUI系列: 1.Android  SystemUI之启动流程(一) 2.Android SystemUI之StatusBar,状态栏(二) 3.Android Syste ...

  3. Android 4.0 ICS SystemUI浅析——StatusBar结构分析

    在上一篇文章<Android 4.0 ICS SystemUI浅析--SystemUI启动流程>中以及提到了SystemUI的组成,本文主要分析其中的StatusBar结构. 1.布局概览 ...

  4. Android P SystemUI之StatusBar UI布局status_bar.xml解析

    相关源码: \frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\phone\CollapsedStatusBar ...

  5. Android 设置系统SystemUI 顶部StatusBar状态栏透明一体化

    参考链接 http://blog.csdn.net/misly_vinky/article/details/12161075 这样修改的确能够把SystemUI StatusBar变成透明的但是有一个 ...

  6. SystemUI StatusBar流程梳理

    SystemUI之StatusBar状态栏 布局结构 下拉菜单.状态栏都是属于statusbar,结构树上也是属于顶层的super_status_bar.xml(StatusBarWindowView ...

  7. Android5.0L因SystemUI ANR导致的黑屏问题分析

    一.问题现象 1.用户直观看到的现象是黑屏. 2.出问题时StatusBar.NavigationBar和墙纸消失. 3.大部分发生在FOTA重启之后,出现概率很低. Platform:MSM8916 ...

  8. Android SystemUI之下拉菜单,通知栏,快捷面板(三)

    Android  SystemUI系列: 1.Android  SystemUI之启动流程(一) 2.Android SystemUI之StatusBar,状态栏(二) 3.Android Syste ...

  9. Android SystemUI之NavigationBar,导航栏(四)

    Android  SystemUI系列: 1.Android  SystemUI之启动流程(一) 2.Android SystemUI之StatusBar,状态栏(二) 3.Android Syste ...

最新文章

  1. 架构模式:MVC与MVVM
  2. NeedforSpeed:SHIFT
  3. 中国产教融合市场发展模式与运营前景咨询报告2022版
  4. python 定义函数为什么有个长线_关于格式化:如何在Python中打破这条长线?
  5. 数据结构与算---重点复习知识
  6. Spring不使用XML的注解开发
  7. 关于std::set的一些补充
  8. 如何截取滚动的页面,窗口
  9. UILAbel 设置了attributedText 后省略号不显示
  10. The most impressed error
  11. 【FLEX教程】#007 如何让JS调用SWF里的方法
  12. android底部蒙版,Android实现蒙版弹出框效果
  13. Linux驱动regulator
  14. DSP C6657 image_processing_evmc6657l网页加载图片示例
  15. opencv打开摄像头和视频文件
  16. 客服管理之如何使用座席劵添加子账号(客服人数)
  17. App.xaml MainWindow.xaml
  18. 【dubbo系列001】dubbo是什么?dubbo解决什么问题?
  19. 20200226省选模拟赛(by Tiw) T1 客星(长链剖分)
  20. 如何删除计算机自动更新补丁,删除自动更新中的WIN10升级补丁

热门文章

  1. 可见性,原子性,有序性的源头(一)
  2. 网络程序设计——VC的多线程编程(线程与进程)
  3. 数学运算符和运算符的优先级
  4. 【题解】百度2020校招Web前端工程师笔试卷(第二批):单选题、多选题
  5. 无线路由器---基本知识
  6. data.length提示undefined
  7. 回望,勉强及格的大学四年答卷
  8. 小清新风格的微信公众号图文这样排版,看过的都说好。
  9. Algorand正式开放测试网TestNet!
  10. BASE32编码 --记录