Android5.1SystemUI详解 - 图文

更新时间:2023-12-16 03:06:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

SystemUI流程分析

(一) 需求 ............................................................................................................................. 2

1. 整体功能结构图 ....................................................................................................... 2 2. 部分界面,功能描述 ............................................................................................... 3 (二) 代码结构 ..................................................................................................................... 6

1. 源码结构和资源文件 ............................................................................................... 7 2. 通知栏,关键类和资源文件: ............................................................................... 8 3. SystemUI类图: ....................................................................................................... 9 (三) 执行流程 ................................................................................................................... 10

1. SystemUI启动......................................................................................................... 10 2. NavigationBar导航栏 ............................................................................................. 13 3. RecentsActivity最近的APP .................................................................................... 14

(1) 第三方APP访问Recent ............................................................................ 15 4. StatusBar加图标AddIcons .................................................................................... 16

(1) Icons排列规则 ........................................................................................... 17 5. QuickSettingPanel快捷开关 .................................................................................. 20 6. ScreenShot事件流程 ............................................................................................. 22 (四) APP与SystemUI交互 .............................................................................................. 24

1. APP通知到PhoneStatusBar .................................................................................. 24 2. APP清除(Cancel)通知 ............................................................................................ 27

(1)需求

SystemUI主要包括状态栏(StatusBar),导航栏(NavigationBar),快捷开关面板(QSPanel)和最近开启的应用面板(RecentPanel);另外,还包括部分锁屏,设置,USB,截屏和音量等部分。

1.整体功能结构图 亮度

WiFi 蓝牙 数据 快捷开关 飞行模式 投射屏幕 手电筒 位置信息 设置 时间 通知栏 状态栏(Icon) 电量 信号 蓝牙 应用Icon WiFi GPS 返回 Back 导航栏 NavigationBar 主键 Home 最近应用 Recent

2.部分界面,功能描述

常态 下拉无通知

下拉通知栏,有通知:

电话

不可清楚通知 可清楚通知 按钮: 清楚所有可清楚通知 下拉,快捷开关 上拉,或点击 通知栏收回,

通知栏下拉,快捷开关:

系统设置 亮度

最近的应用

状态栏,Icon区域

红色:notificationIcons,通知图标,比如我们常见的360以及QQ等等,都会在这里显示自己的图标;

紫色:statusIcons,状态图标,这里会放置系统的一些状态图标,比如像蓝牙、闹钟、耳机插入等等;

绿色:signal_battery_cluster,信号以及电量图标,这里主要放置了wifi以及手机信号和电池电量的图标(注:没有插入SIM卡);

关组件,startServicesIfNeeded(),这里启动了各种Service,但是它们并不是真正的Service ,是继承了SystemUI.java这个抽象类,复写了start()方法。

这几个UI组件,重点关注SystemBars的start()方法;它又启动了

ServiceMonitor的start()方法;在此方法里面,通过Handler发

mHandler.sendEmptyMessage消息,分别调用了 StartService() 和 continueStartService()两个方法。

然后,调用:mCallbacks.onNoService();回到SystemBars 的对象中;这里调用关键方法:createStatusBarFromConfig();这里面的取值:R.string.config_statusBarComponent实际就是PhoneStatusBar;

配置文件:base/packages/SystemUI/res/values/config.xml; 这样就调到了PhoneStatusBar的start()方法。同时PhoneStatusBar在start()方法里面也调用了父类BaseStatusBar的start();从这里一些列,将NavigationBar和

QuickSettingPanel初始化好,添加到UI中。

SystemBars 中关键代码段:

启动时序图:

2.NavigationBar

导航栏

PhoneStatusBar类的start()方法里面调用 addNavigationBar() ; 流程如上图,第 9 步;然后此方法内调用 prepareNavigationBarView();最后 WindowManager调addView将NavigationBarView添加到 UI 界面。

NavigationBar主要包含三个按钮:

Back,Home和Recent。

PhoneStatusBar类中 prepareNavigationBarView() 方法代码段:

3.RecentsActivity

最近的APP

上一步,初始化NavigationBar时,初始化了Recent的点击事件;

mRecentsClickListener:

mRecentsClickListener 事件定义:

这里 toggleRecentApps() 方法给BaseStatusBar发Handler消息 Message;

程如下,时序图:

Recent是SystemUI的之类;Recent启动RecentsActivity; RecentsActivity里面装载RecentPanelView;

如果RecentTaskLoader取得的FirstTask为Null,则显示无最近打开的APP。否在刷新显示列表(refreshRecentTasksList()), 后台加载最近打开的APP列表loadTasksInBackground() 。

(1)第三方APP访问Recent

Recent键的点击事件是在framework层进行处理的,不再往下传递;因此第三方APP在onKeyDown()与dispatchKeyEvent()方法中都不能捕获RECENT_APP_KEY的动作。

不过,在应用中添加以下代码就可以屏蔽了RECNET_APP_KEY:

4.StatusBar

加图标AddIcons

这里的流程,需要参考到前面的SystemUI的类图,PhoneStatusBar继承自 BaseStatusBar,而BaseStatusBar实现了CommandQueue里的Callbacks接口;而这个接口里面有个关键的addIcon() 方法。

PhoneStatusBar的start() 方法里面调用PhoneStatusBarPolicy的构造器; 注意:这里现在所有的Icon初始,都是不可见的。

此构造器代码片段:

然后,后面依次调

用StatusBarMa

nager,StatusBarManagerService和 CommandQueue的setIcon()方法;

再然后CommandQueue对象回调PhoneStatusBar的AddIcon()方法;最后通过mStatusIconsKeyguard.addView()方法,将Icon显示到界面上。

最后,那些图标真的需要显示了,是通过接收系统广播,然后动态显示,如下图的StatusBarManager对象的setIcon()调用关系:

此部分时序图如下:

(1)Icons排列规则

状态栏的布局文件:

frameworks/base/packages/SystemUI/res/layout/status_bar.xml

此文件 又依次包含下面两个文件:

frameworks/base/packages/SystemUI/res/layout/system_icons.xml

frameworks/base/packages/SystemUI/res/layout/signal_cluster_view.xml

总体来说,Icons的排列分四个区域,容器是 PhoneStatusBarView;com.android.systemui.statusbar.phone.PhoneStatusBarView;它是继承自 PanelBar extends FrameLayout ;

四个区域中,

三个常态从左往右,分别是:应用通知区(gone过量)、系统图标、时钟区; 另外一个动态浮动显示区域,通知提示区(ticker_stub);

系统图标又包含三部分:状态图标、信号区、电量区(默认gone电量百分比);

信号区域包括:VPN、WiFi、手机信号、飞行模式、no_sims;

以上各区域,关系结构图如下:

通知栏 (浮动)通知提示区(ticker_stub) (常态)状态栏 应用通知过量(gone) 应用通知区 系统图标区 信号区 状态 电量icon 手机信号 飞行模式 VPN WiFi

各图标和区域,宽度与互挤原则如下:

时钟 电量百分比(gone) no_sims

其中,只有最左边的 应用通知区 设置了权重,因而它可以得到更多的区域(在其他区动态不显示的时候),如下图XML文件。

其他区域宽度基本都是 (wrap_content);

另外有三个固定宽度,和一个占满宽度(match_parent) ticker :

电量图标宽度9.5dp,

如下图:

wifi_signal_spacer和wifi_airplane_spacer宽高4dp,可见性gone:

5.QuickSettingPanel快捷开关

QSTitleHost.Java中定义快捷开关的各个标题createTiles():代码如下:

此方法在recreateTiles() 中调用,而recreateTiles() 又是在QSTitleHost的构造器中被调用,

QSTitleHost被构造好之后,为QSPanel对象配置QSTitleHost和标题;然后给顶部状态View设置QSPanel;最后为QSTitleHost设置CallBack回调方法。

PhoneStatusBar.Java中,相关代码如下:

QuickSettingPanel时序图:

6.ScreenShot

事件流程

Android原生截屏是同时按下 电源键 和 音量减,开始截屏,

Android源码中对按键的捕获位于文件PhoneWindowManager.java (\\frameworks\\base\\policy\\src\\com\\android\\internal\\policy\\impl) 中;我们可以在interceptKeyBeforeQueueing()中看到,按下截屏组合键之后,进入interceptScreenshotChord()方法,此方法比较关键,代码如下:

这里进行了判断,是否截屏可用,是否已经按下电源键和音量减,然后Handler处理mScreenshotRunnable线程;线程里调用takeScreenshot()方法开始截屏;

方法中通过bindServiceAsUser(),启动服务TakeScreenshotService.Java,TakeScreenshotService在onBind()事件中,调用handle启动GlobalScreenshot.Java对象进行真正的截屏操作mScreenshot.takeScreenshot();这里也是多线程操作。

基本上快到最关键最核心的地方了,在此方法中,和以前的Android版本有些不同,之前的surface操作是写到surface类里,现在增加了这个surfacecontrol类来控制surface

最后,跟到Surfacecontrol里面就到了 底层 native方法了:nativeScreenshot()

UML时序图如下:

(4)APP

1.APP

与SystemUI交互

通知到PhoneStatusBar

第三方APP的Notification怎么调用到SystemUI里的PhoneStatusBar呢;

首先APP通过调用android.app.NotificationManager的Notify方法,调用到 com.android.server.notification.NotificationManagerService的此SystemService的 enqueueNotificationWithTag()方法,再进入到enqueueNotificationInternal()方法。

这里是frameworks层,不在SystemUI工程了; 这三个类文件的位置:

frameworks/base/core/java/android/app/NotificationManager.java

....../base/core/java/android/service/notification/NotificationListenerService.java ....../core/java/com/android/server/notification/NotificationManagerService.java

还包括NotificationManagerService的内部类:NotificationListeners ;

和NotificationListenerService的内部类:INotificationListenerWrapper ;

enqueueNotificationInternal()方法,代码比较多,该方法对Notification进行了组装, 还做了安全性检查,限制每个应用最多只能提交50个通知;这是防止恶意

软件注册大量通知。

接下来,是根

据通知重要性,对其进行打分,分数在 -20到20 之间;

然后是对Notification的组装,然后对Notification的icon进行判断,若其不为零,便为有效通知,之后调用关键方法notifyPostedLocked():

到这里做了可见性的一些判断,就开始准备回调了,因为前面通知已经组装完毕准备显示到状态栏了,之后就需要将相关的通知消息告诉所有监听者。继续看到notifyPostedLocked()中调到的notifyPosted()方法:

这里INotificationListener的实现类是NotificationListenerService.Java;到这里就调到Listener的onNotificationPosted()方法;此方法是一个空的抽象方法;是由它的APP实例类来实现的。源码截图如下:

此方法,在BaseStatusBar类中实现,new NotificationListenerService() { ... 如下图:

};

时序图如下:

2.APP

清除(Cancel)通知

与\新增通知\类似的流程是\删除通知\,发起点在NotificationManager,之后经由NotificationManagerService处理和NotificationListenerService传递,最后到达各个继承自NotificationListenerService的子类中,只不过最后的处理方法变成了onNotificationRemoved。调用时序图下:

NotificationListenerService调用流程小结

简单来看,NotificationListenerService在系统通知的消息传递过程中,起到了代理的作用。继承自NotificationListenerService的类作为client端,真正的server端则是NotificationManagerService,由它负责整个Notification的控制与管理。NotificationManagerService将处理之后的结果通过NotificationListenerService返回给client端,最终各个client端(BaseStatusBar)通过onNotificationPosted()和onNotificationRemoved()方法拿到系统通知状态变更的相关信息。

一. 锁屏界面下拉通知如何实现 1. 线索点 A. 下拉、上拉时会触发NotificationPanelView.setNotifyStackExpansion B. 关闭屏幕时会触发PanelView.setExpandedHeightInternal

本文来源:https://www.bwwdw.com/article/v3i5.html

Top