Android SystemUI概览
简介:SystemUI是为用户提供系统级别的信息显示与交互的一套UI组件,例如屏幕顶端的状态栏,底部的导航栏,图片壁纸以及RecentPanel(近期使用的APP列表),TakeScreenShotService(截屏服务),PowerUI(低电量警告),RingtonePlayer(播放铃声).
以下是小米4SystemUI对应的包
Android原生SystemUI:http://androidxref.com/4.2_r1/xref/frameworks/base/packages/SystemUI/src/com/android/systemui/
SystemUI是怎样运行的
SystemUI功能很多,并且大部分功能之间相互独立,比如RecentPanel,TakeScreenShotService等均是按需启动,并在完成其既定任务后退出,这与普通的Activity以及Service是一样的.
比较特殊的是状态栏,导航栏等组件的启动方式.它们运行与一个称为SystemUIService的Service中。因此状态栏与导航栏的启动过程就是SystemUIService的启动过程.
PowerUI:主要是通过注册一些相关的广播,然后弹出Dialog.
RingtonePlayer:初始化一些配置,比如获取IAudioService及一些回调等待调用.
StatusBar的创建(重点)
系统会根据屏幕的宽高来判断采用PhoneStatusBar(手机 状态栏与导航栏分离)或者TabletStatusBar(PAD),这个判断存在于PhoneWindowManager.setInitialDispalySize()方法中(在此不作分析)
下面请看PhoneStatusBar的start()方法
1.super.start();
2.addNavigationBar();//创建导航栏
3.mIconPolicy=new PhoneStatusBarPolicy(mContext);定义了系统通知图标的设置策略
下面看BaseStatusBar.start()方法
代码省略,简述流程
1.获取IStatusBarService,IStatusBarService是运行于system_server的一个系统服务,它接受操作状态栏/导航栏的请求并将其转发给BaseStatusBar.为了保证SytemUI意外退出后不会发生信息丢失,IStatusBarService保存了所有需要状态栏与导航栏进行显示或处理的信息副本。
2.将一个继承自IStatusBar.Stub的CommandQueue的实例注册到IStatusBarService以建立通信,并将信息副本取回。
3.通过调用子类的createAndAddWindows()方法完成状态栏与导航栏的控件树及窗口的创建于显示
4.使用从IStatusBarService取回的信息副本
小结:StatusBarManagerService是SystemUI中的状态栏与导航栏在system_server中的代理.所有对状态栏或导航栏有需求的对象都可以通过获取StatusBarManagerService的实例或Bp端达到其目的。只不过使用者必须拥有能够完成操作的相应权限.
举例:StatusBarManagerService.setIcon()
public void setIcon(String slot, String iconPackage, int iconId, int iconLevel,String contentDescription) {
synchronized (mIcons) {
int index = mIcons.getSlotIndex(slot);
if (index < 0) {
throw newSecurityException("invalid status bar icon slot: " + slot);
}
StatusBarIcon icon = new StatusBarIcon(iconPackage, UserHandle.OWNER, iconId, iconLevel, 0, contentDescription);
try {
} catch (RemoteExceptionex) {
}
}
}
}
综述SystemUI的体系结构:
SystemUIService,一个普通的Android服务,它以一个容器的角色运行与SystemUI进程中。在它内部运行着多个子服务,其中之一便是状态栏与导航栏的实现者—BaseStatusBar的子类之一。
IStatusBarService,即系统服务StatusBarManagerService是状态栏/导航栏向外界提供服务的前段接口,运行与system_server进程中.
BaseStatusBar及其子类是状态栏与导航栏的实际实现者,运行与SystemUIService中。
IStatusBar,即SystemUI中的CommandQueue是联系StatusBarManagerService与BaseStatusBar的桥梁。
SystemUI中还包含了ImageWallpaper,RecentPanel以及TakeScreenshotService等功能的实现。它们是Service,Activity等标准的Android应用程序组件,并且互相独立。 其中RecentPanel在小米4中的存在形式为Window+控件树
深入理解状态栏:
时间信息:
监听几个和时间相关的广播:ACTION_TIME_TICK,ACTION_TIME_CHANGE,ACTION_TIMEZONE_CHANGED,ACTION_CONFIGURATION_CHANGED从而改变时间显示
电量信息:
一个被BatterController类所管理的ImageView。通过监听android.intent.action.BATTERY_CHANGED广播以从BetterService中获取电量从而更新ImageView的显示
信号信息:
同电量信息一样,只不过是被NetworkController类中监听与信息相关的广播
通知信息:
通过StatusBarManagerService所提供的接口向状态栏中添加或删除一条通知信息,这个信息可以在状态栏左侧显示一个图标以引起用户的注意,并在下拉卷帘中为用户显示更加详细的信息。更为详细的理解,可以从通知是怎么添加开始着手看源码。
系统状态图标区:
通过StatusBarManagerService的setIcon()接口改变状态栏中系统图标区的显示
其中frameworks/base/core/res/res/values/config.xml中的字符串数组资源config_statusBarIcons定义了一个准许显示在系统状态区的预定义的意图列表
从setIcon这个方法的前两个参数中可以看出.
slot:一个字符串,用于声明图标的意图,这个意图必须在前面所说的数组中定义的。
icon:一个用于显示的图标资源id
note:尽管StatusManager提供了设置系统图标的接口,不过一般都是使用PhoneStatusBarPolicy类进行设置的。这个类在PhoneStatusBar.start()方法最后被实例化,这个类与NetworkController,BatteryController等组件一样,通过监听一系列与系统状态相关的广播,并在这些广播到来之时通过调用StatusBarManager.setIcon()接口修改系统状态区。
深入理解导航栏:
在PhoneStatusBar的makeStatusBarView()方法中不仅创建了状态栏控件树,也创建了导航栏控件树,然后在PhoneStatusBar.start()方法中调用addNavigationBar()添加到窗口。更为具体的实现又与输入系统相关联(每个虚拟键都是个一个自定义控件KeyButtonView,通过InputDispatcher所提供的injectInputEvent()方法将派发给KeyButton的一系列触摸事件转化为按键事件).
note:Android官方提供的SystemUI的导航栏还支持滑动导航栏出现搜索界面(SearchPanel到搜索Activity),这个根据不同系统的ROM会不一样。
导航栏中又涉及到以下知识点:
1.菜单键的可见性
2.修改BACK键的图标
3.导航栏方向的选择
4.低辨识度模式
5.禁用一些功能 :
通过StatusBarManager以及StatusBarManagerService为应用程序以及系统服务提供了操作状态栏与导航栏的所有接口,但是这些接口并不适用与那些没有系统签名的普通应用程序。那么普通应用程序想操作状态栏和导航栏就必须使用SystemUIVisibility
Android壁纸:
WallpaperService与Engine
WallpaperManagerService
WindowManagerService