systemUI之statusBar
来源:互联网 发布:sketch up mac 破解版 编辑:程序博客网 时间:2024/06/07 02:59
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 IStatusBar interface. 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 IStatusBar interface. 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 state int 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 state N = 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 view final 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 possible final 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 notification mBatteryController = new BatteryController(mContext); mBatteryController.addIconView((ImageView)sb.findViewById(R.id.battery)); mNetworkController = new NetworkController(mContext);//5.加载并更新RecentsPanelView。 // RecentsPanel mRecentTasksLoader = new RecentTasksLoader(context); updateRecentsPanel();//6.注册定制的监听器。 // receive broadcasts IntentFilter 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
- systemUI之statusbar
- Android 5.1 SystemUi 之 StatusBar的简单分析
- Android 5.1 SystemUi 之 StatusBar的简单分析
- systemui statusbar service 小结
- Andorid SystemUI, StatusBar, Keyguard
- Android 4.0 ICS SystemUI浅析——StatusBar工作流程之时间日期设置
- Android 4.0 ICS SystemUI浅析——StatusBar加载流程之Notification
- Android 4.0 ICS SystemUI浅析——StatusBar加载流程之Notification
- Android 4.0 ICS SystemUI浅析——StatusBar工作流程之时间日期设置
- Android系统应用---SystemUI之二:Statusbar显示流程以及系统状态图标更新分析
- SystemUI statusbar 更换自己的UI图标
- Android自定义状态栏statusBar替换系统SystemUI
- Android 4.0 ICS SystemUI浅析——StatusBar结构分析
- Android 4.0 ICS SystemUI浅析——StatusBar结构分析!!
- Android 4.0 ICS SystemUI浅析——StatusBar结构分析
- Android 4.0 ICS SystemUI浅析——StatusBar结构分析
- Android 4.0 ICS SystemUI浅析——StatusBar结构分析
- word2003无法打开,只能安全模式打开的解决方法
- Link-Cut Tree
- Android学习笔记 安全沙箱 重启操作等
- java中Class.getResource用法
- java网站建设1-准备工作 spring包分析
- systemUI之statusBar
- 在linux下如何使用Makefile对fortran程序进行编译
- 去除重复Sql数据取得单条记录数据的方法
- jquerymobile-4 header和data-icon
- Android中Activity之间数据传递的几种方法总结
- RamDisk 学习
- JSP连接ACCESS数据库方法
- 聊天,如何制造话题
- Win7 64位 IIS未能加载文件或程序集“System.Data.SQLite”或它的某一个依赖项