搜索
 找回密码
 立即注册

简单一步 , 微信登陆

system ui statusbar

作者:liuwei | 时间:2016-9-28 10:52:13 | 阅读:5352| 只看该作者
第一部分状态栏总体介绍
1、整体功能介绍,功能操作说明
    自 android2.2 开始 , 原本存在与 framework-res.apk 中的状态栏和下拉通知栏界面控制被分割出一个单独的 apk文件 , 命名为 SystemUI.apk, 保存在 System/app 文件夹中。在 SystemUI.apk 中 , 保存着状态栏的图标 ,xml文件和控制文件等 , 这样的分割 , 使我们可以更方便地去对其进行修改。
状态栏主要用来显示一些系统图标,应用的通知图标和系统时间。 状态栏模块就是控制和管理着这些图标,以及通知信息的显示和一些系统开关的。
Ⅰ、状态栏的通知功能(包括时间,通知,系统状态等)
状态栏与 Toast 都可以起到通知、提醒的作用。但它们的实现原理和表现形式却完全不一样。 Toast 其实相当于一个 Widget 组件,有些类似于没有按钮的对话框。而 状态栏可与系统其它应用进行交互来显示在屏幕上方状态栏中的信息,并且 状态栏还可通过图标的显示变化来反应一些系统状态的变换,如电池电量, wifi ,蓝牙,闹钟等。状态栏 是一种让你的应用程序或系统信息变化在不使用 Activity 的情况下给用户的提醒和通知。
Ⅱ、状态栏的日期显示
      状态栏也会显示系统时间,当前日期也会在状态栏显示,只是在默认情况下,日期是隐藏的,只有在下拉状态栏时才会显示, 4.3平台的下拉状态栏的时间和日期显示与4.1大体是一致的,唯一的不同是4.3的时间日期是可以点击的,直接跳到设置界面的进行编辑,操作更加方便,快捷。
III、状态栏的快捷开关功能
    这一功能的设计主要是对系统开关的打开与关闭的操作,通常这些功能是要进入设置界面进行改变的,现在状态栏增加该功能后,直接下拉状态栏便可对其状态进行改变。
2、启动流程
首先我们从SystemUI的AndroidManifest文件可以发现:整个SystemUI是由"SystemUIService"这个服务启动的,而"SystemUIService"这个服务是在SystemServer.java通过startSystemUi方法进行启动的。
接下来,SystemUIService类执行自己的onCreate()方法,这个方法中首先要判断当前要启动的是手机的statusbar service,还是平板的statusbar service。判断结束后,代码调用是mServices.start()方法,即调用SystemUI类的Start()方法;SystemUI类又是被BaseStatusBar类实现的;PhoneStatusBar类又继承了BaseStatusBar类,重写了start()方法,因此实际调用的是PhoneStatusBar的start()方法来完成状态栏的启动。
以上主要是4.1状态栏的启动过程,4.3状态栏的启动与4.1基本是一致,只是多了一个用户信息的设置,这个主要与通知栏快捷设置有关。
3、Android4.3状态栏整体框架图(按照层次结构,划分出各个模块,包括使用的外部模块):
在android中,状态栏不属于某个应用程序,而是系统的一部分,是通过StatusBarService来管理维护的,整个模块的位置:framework/base/packages/SystemUI。
要研究状态栏,首先我们从状态栏的布局文件入手来研究它的整体层次结构,文件位置:framework/base/packages/SystemUI/res/layout//status_bar.xml(单sim卡布局)
framework/base/packages/SystemUI/res/layout/msim_status_bar.xml(多sim卡布局)
这两者之间的区别主要在于单sim卡与多sim卡,单sim卡比较好理解,就是它的布局文件中sim卡信号显示对应的id注册只有一个,而多sim卡比较复杂,它主要还分为CT模式(电信sim卡信号的显示模式),CU模式(联通sim卡信号的显示模式)以及我们默认的信号显示模式,如果没有特别指定,我们一般用的都是default模式,它的布局文件中sim卡信号显示对应的id注册会有多个(4.1是两个,4.3对应的是三个)。
根据布局文件,我们画出结构图,对状态栏有一个整体的了解:
状态栏顶层view布局:
file:///C:/Users/liuwei/AppData/Local/YNote/data/liuwei372**34@163.com/70e6d12ef521450db06b9ca9bc1a2eb3/lip_image004.gif
                               图2.1
状态栏顶层的view一般分为两部分:状态栏静止显示的图标和收到通知以后动态显示的图标。
静止显示的图标又分为两部分:状态栏左侧的状态图标和状态栏右侧的静态图标,状态图标一般是不显示,只有在一定条件下才会显示,比如说是状态栏接收到通知等等,才会出现;而静态图标,一般情况下只要打开系统的一些开关,系统的时间,电池电量图标等等,它都是会显示。
要说到动态显示的图标,最常见的,比如说导入导出联系人等等,你都会看到状态栏上出现的图标与文字的切换等等。
状态栏下拉界面view布局:
     file:///C:/Users/liuwei/AppData/Local/YNote/data/liuwei372**34@163.com/d24ab3cea62640f2b323004b9b627c23/lip_image006.gif
                                图2.2
下拉状态栏view显示,这个最主要的显示便是通知的具体显示了,不论系统的通知,第三方应用的通知都会在该界面以图标加文字的形式显示出来,相较于4.1,4.3新增加了一个专门显示快捷开关的界面。
根据状态栏的整体功能结构,我们将状态栏整体划分为以下三大模块:

3、文字描述每个层次的功能说明,以及每一个层次的模块功能说明,并说明各个模块之间的交互关系:

(1) 通知模块:显示系统发出通知的内容,有图标和文字的简短显示。
(2) 静态图标显示模块:系统设备的当前状态,例如打开了WIFI,蓝牙,闹钟,静音模式或是震动模式后,此区域都会显示相对应的图标。上图显示的就是打开的Wifi,蓝牙,闹钟后的图标显示。
(3) 快捷开关模块:这在4.1上显示在状态栏下拉界面的底部的,4.3与4.1不同,它是专门给该功能分配了一个panel进行显示。
快捷开关的打开,都会显示在状态栏的静态图标对应区域,状态栏收到通知后也会在状态栏的左侧区域进行显示。

第二部分分模块说明
1模块功能具体介绍
    1. 通知(Notification)的介绍:

对于通知,应先明白:通知概要 通知标题 通知内容 通知图标 通知时间

    内容
     说明
对应的方法
   通知概要
通知发过来后,首先显示在状态栏顶部的提示消息
Builder类中的setTicker方法,或是Notification类中的tickerText 属性
   通知图标
通知在状态栏上显示的图标
Builder类中的setSmallIcon方法或是Notification类中的icon 属性
   通知标题
通知的简单说明
Builder类中的
setContentTitle方法或是Notification类中的
setLatestEventInfo方法中直接添加
   通知内容
通知的具体内容
Builder类中的
setContentText方法或是在
Notification类中的
setLatestEventInfo方法中直接添加
    1. 快捷开关的作用

file:///C:/Users/liuwei/AppData/Local/YNote/data/liuwei372**34@163.com/5087c5bb42694bb59c97a6fe796b6c12/ip_image030.jpegfile:///C:/Users/liuwei/AppData/Local/YNote/data/liuwei372**34@163.com/e6d8e3ab447c49eeb685a5137b68b187/ip_image032.jpegfile:///C:/Users/liuwei/AppData/Local/YNote/data/liuwei372**34@163.com/3251f921cb94439fbe92519f99d40526/ip_image034.jpeg
                    图1.1  4.1状态栏的快捷开关
file:///C:/Users/liuwei/AppData/Local/YNote/data/liuwei372**34@163.com/2de3d5ddb7e140458b81c62942109289/ip_image036.jpeg
                    图1.2  4.3状态栏的快捷开关
如上图所示为4.1的上快捷开关的显示效果,总共有11种,从左至右依次为:
Wifi开关,蓝牙开关,位置访问开关,数据同步开关,移动数据开关,飞行模式开关,亮度调节开关,屏幕旋转开关,锁屏开关,声音模式开关以及关机开关,所有的这些开关在设置界面都可以进行相应的设置,但是快捷开关的设计使得这些功能的启用和关闭更加快捷。
       (3)Sim卡信号显示刷新
file:///C:/Users/liuwei/AppData/Local/YNote/data/liuwei372**34@163.com/c38b9f572fcb48c5a1c1d0ae28de4dfd/lip_image038.gif
                     图1.3 sim卡信号显示图标
  如上图所示,为状态栏中的双sim卡显示,4.3的sim卡布局是和4.1是一样的,它都是与wifi的布局绑定在一起的。SIM卡信号一般包含:信号强度、数据类型(包含数据连接的图标标识)、网络类型等
file:///C:/Users/liuwei/AppData/Local/YNote/data/liuwei372**34@163.com/42ae2b7f81234875803b6f3671be9d38/ip_image040.jpeg该图为default下的信号显示图。
file:///C:/Users/liuwei/AppData/Local/YNote/data/liuwei372**34@163.com/76e7bfc021834e65925dc553c47d86a9/ip_image042.jpeg 该图为CT模式(电信)下信号的显示图。
file:///C:/Users/liuwei/AppData/Local/YNote/data/liuwei372**34@163.com/184e034554a34c2699afbcabb9d74cb9/ip_image044.jpeg该图为CU模式(联通)下的信号显示图
2、模块的框架原理以及模块类图以及每个类的功能
   状态栏主要包含通知的显示加载,Sim卡信号的显示,快捷开关的显示以及状态栏中图标的更新,下面主要从这四个方面对状态栏做一个详细的说明:
(1)     通知的显示:
file:///C:/Users/liuwei/AppData/Local/YNote/data/liuwei372**34@163.com/17b52536f8014d7b8b7bbb668be5b634/lip_image046.gif
                  图2.1 通知的加载流程及显示原理
主要类的作用说明:
PhoneStatusBar类路径:
framework/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/
PhoneStatusBar类为SystemUIService服务启动的第一个类,主要用于状态栏View的绘制及相应布局的加载,例如,状态栏的整体布局,sim卡布局,快捷开关布局,状态图标的布局等都是在该类的view绘制方法中进行初始化的。
BaseStatusBar类路径:
framework/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/
BaseStatusBar是PhoneStatusBar的父类,继承了SystemUI抽象类,实现了CommandQueue.Callbacks接口中的方法,例如通知的更新方法,图标的更新方法等,都是在这个类中实现的。                     
StatsubarManagerService类路径:
framework/base/services/java/com/android/server
是一个系统级服务,这个类是一个IBinder的实现类,是systemui的业务实现类。4.1和4.3平台,此类没有什么太大的改变。
CommandQueue类:
framework/base/packages/SystemUI/src/com/android/systemui/statusbar/
派生于IStatusBar.Stub,有一个内部接口Callbacks,这个接口的实现就是StatusBarService,用于处理状态栏、通知相关的请求,内部维护了一个事件队列,添加通知的方法会创建一个MSG_ADD_NOTIFICATION的massege,发送给进行Handler处理,CommandQueue、StatusBarService和StatusBarManager属于同一个进程,而StatusBarManagerService是一个系统级服务,它们之间必然需要通过IBinder进程间通信。
NotificationManagerService类:
framework/base/services/java/com/android/server/
该类是由INotificationManager.Stub派生出来的,它实现了INotificationManager接口中定义的相关方法并向外部提供服务的类。主要向外提供enqueueNotificationWithTag()方法。该方法实际上是调用enqueueNotificationInternal(),他里面提供了对通知的发送上限,通知的声音播放,通知是否闪光等功能的具体处理。
NotificationManager类:framework/base/core/java/android/app/
该类主要是调用NotificationManagerService中的方法,例如通知的发送是调用NotificationManager中的notify方法,最终是调到NotificationManagerService中的enqueueNotificationInternal方法去做具体实现的。
(2)  信号图标更新:
file:///C:/Users/liuwei/AppData/Local/YNote/data/liuwei372**34@163.com/14e6bcacc7374fcd903afec52a93e578/lip_image048.gif状态栏信号主要指的是wifi和SIM卡信号;根据不同机型SIM卡信号部分又分为单卡和多卡,多卡根据不同运营商要求又分为CT(电信)、CU(联通)、DEFAULT(默认)三种显示外观。
Wifi和SIM卡信号更新框架基本相同,简单的流程如下图:
file:///C:/Users/liuwei/AppData/Local/YNote/data/liuwei372**34@163.com/56f68d507d874135b8645da1f3f1f633/lip_image050.gif
信号更新原理(多SIM卡以Dedalut模式为例)
按照以上所述信号更新的基本框图,首先状态栏需要加载承载信号显示的view,该view是在整个状态栏view初始绘制的时候加载,具体是在PhoneStatusBar类的注册对应的view。接着进入整个信号刷新类中MSimNetworkController,信号的实时刷新入口即是相应action;action触发执行各信号信号值的确定,通过该类的信号刷新方法调用接口传递信号值至图标显示更新类MSimSignalClusterView,并最终在此实现显示图标的更新。
        具体的wifi及sim卡更新见图3.3和图3.4。
单卡更新原理基本和多卡Dedalut模式相同,不同的是信号刷新类对应的是NetworkController;实际上多卡信号刷新类继承的也是NetworkController,因而其中原理基本一致,此处不做解释。
(3)状态栏图标显示,更新
file:///C:/Users/liuwei/AppData/Local/YNote/data/liuwei372**34@163.com/ad2f007e7e44429d85f577b200a975ab/lip_image052.gif                          图2.2 状态栏图标的加载及显示原理
PhonesStatusBarPolicy类路径:
framework/base/packages/SystemUI/com/android/systemui/statusbar/phone/
该类主要注册了一个广播接收器,接收闹钟,数据同步,蓝牙,声音,sim卡状态等状态改变时发过来的广播,改变状态栏上对应的图标显示。
1 通过广播机制,StatusBarPolicy中注册的广播接收器收到BatteryService广播的电池状态改变的事件触发;
2 调用StatusBarPolicy类中对应的更新方法开始更新状态栏中对应的图标显示。
3 从intent中解析需要的字段,调用StatusBarManager的设置图标的方法。StatusBarManager是客户端使用的状态栏管理类;
4 通过IBinder机制跨进程调用StatusBarManagerService的设置图标的方法。StatusBarManagerService派生于IStatusBarService.Stub,是状态栏管理的服务端,是具体实现;
5 StatusBarManagerService有一个StatusBarIconList成员,这个list成员在StatusBarManagerService创建时,从配置文件中加载生成。StatusBarManagerService的设置图标的过程中,又会从配置文件中获取对应字段在StatusBarIconList中的索引,再由包名、图片id,创建StatusBarIcon实例,并根据StatusBarIconList中所获得索引对应项更新该实例。
6 调用CommandQueue的设置图标的方法。 CommandQueue用于处理状态栏、通知相关的请求,内部维护了一个事件队列,此时会创建一个设置图标的消息,发送给Handler进行处理;
7 CommandQueue内部也有一个StatusBarIconList实例,这个实例是由StatusBarService创建。在处理设置图标的消息之前,会先通过获得图标索引的方法获得图标的位置索引,再更新StatusBarIconList,最后调用Callbacks,也就是StatusBarService的添加图标的方法进行添加或者更新图标的方法进行更新。
    1. 快捷开关显示,更新

file:///C:/Users/liuwei/AppData/Local/YNote/data/liuwei372**34@163.com/93d81d2c30ef4adcbf043f93daa4240c/lip_image054.gif
如上图1.1与1.2所示,分别为4.1与4.3的快捷开关的显示界面,4.1模式是将快捷开关直接显示在下拉状态栏的底部,但是4.3是将其全部显示在一个界面中,这里着重描述一下4.3的加载模式,首先在PhoneStatusBar的makeStatusBarView方法中,首先创建一个QuickSetting类,这个类主要用于创建和显示这16种开关,4.3原生代码中已经添加了相应的代码处理,但是大多数是用开关控制的,所以我们只有打开开关才会将其显示出来。这里我们要特别关注QuickSettingsContainerView这个类,它主要的作用就是让整个快捷开关在其上面加载,所以是必不可少的。最后就是通过QuickSetting类的setUp方法真正去创建快捷开关,这个方法是和sim卡的数量,蓝牙的状态,位置信息的状态,以及电池电量的状态都有关,所以提前需加载以及更新好其当前的状态图标。
3模块主要时序图
file:///C:/Users/liuwei/AppData/Local/YNote/data/liuwei372**34@163.com/c8bcfe52dff9404eae2a8752297d9c19/lip_image056.gif
                     图3.1通知的加载显示时序图
file:///C:/Users/liuwei/AppData/Local/YNote/data/liuwei372**34@163.com/8f2293f5f9ac420fb09454b760fe9063/lip_image058.gif
                           
图3.2状态图标添加更新时序图
file:///C:/Users/liuwei/AppData/Local/YNote/data/liuwei372**34@163.com/b87cb125627d4a50b8822137fb190136/lip_image060.gif
                            图3.3 wifi更新时序图
file:///C:/Users/liuwei/AppData/Local/YNote/data/liuwei372**34@163.com/dad8d9f3fc1c4ad89c03efb0ecb4f36d/lip_image062.gif
图3.4 默认模式下的sim卡信号更新时序图
file:///C:/Users/liuwei/AppData/Local/YNote/data/liuwei372**34@163.com/099fd02f52374043ad4fd2fd40a3acf2/lip_image064.gif
图3.5快捷开关显示时序图
4、对外接口及使用的外部接口
通知显示是在状态栏的BaseStatusBar类中进行处理的,它主要调用的外部接口就是IStatusBarService,该接口由StatusBarManagerService来实现,该类里边提供了将通知以一个键值对的形式存放在一个map集合中,键为一个IBinder对象,值为一个StatusBarNotification对象,后续的通知显示就是从该map集合中取出来的。
通知的管理类是NotificationManagerService,该类是由INotificationManager.Stub派生出来的,它是用来实现接口INotificationManager中定义的相关方法并向外部提供服务的类,它里面提供了通知的具体处理方法,主要由NotificationManager调用。
状态栏对外提供的接口为IStatusBar,它的实现类为CommandQueue,该类中提供了添加通知,更新通知以及删除通知的相应方法,该方法会发送其相应的消息给handler,最后调用Callbacks接口中的对应方法,也就是StatusBarService对通知进行处理的方法。
状态栏图标的添加,刷新与通知的调用流程是一样的,只是其中调用的方法是图标对应的方法,这里不再作解释。
信号更新中主要使用了MSimNetworkController.MSimSignalCluster,该接口中定义了三个方法:
1.用于实现wifi状态值的显示更新
           2.用于SIM卡信号的显示更新;
3.用于飞行模式与信号更新的显示更新;
接口实现类MSimSignalClusterView,该接口是衔接信号更新值和相应显示view的桥梁,通过接口的3个方法的实现最终将更新的信号值转化为对应的新状态图标显示出来。

收藏
收藏0
分享
分享
点赞
点赞0
反对
反对0
回复

使用道具 举报

大神点评2

沙发#
Robby.zou 发表于:2016-9-28 10:56:06
太长了吧!
该会员没有填写今日想说内容.
回复

使用道具 举报

板凳#
creass 发表于:2016-9-28 10:57:50
hahaahhahaha!!123
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册
手机版