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处理挂载流程都有很多东西值得去挖掘,日后陆续放出吧。
分享到:
相关推荐
Android 4.0 ICS SystemUI浅析——StatusBar结构分析中所涉及到的全部图片。
StatusBar流程梳理-F
Android 4.0 ICS SystemUI浅析——StatusBar工作流程之时间日期设置文中涉及到的图片以及代码。 文章地址:http://blog.csdn.net/yihongyuelan
SystemUI:StatusBar,Notification,PowerUI,SettingsUI,Recents,RingtonePlayer..
Android 8.1实现底部虚拟...frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
AndroidP横屏项目,修改SystemUI下拉栏全屏显示,并覆盖NavigationBar导航栏之上,原博客 https://blog.csdn.net/shusuanly/article/details/115264404
Android5.1 SystemUI整体功能结构图, ...StatusBar加图标AddIcons;Icons排列规则; QuickSettingPanel快捷开关; ScreenShot事件流程; APP与SystemUI交互: APP通知到PhoneStatusBar; APP清除(Cancel)通知。
Android系统定制-SystemUI-下拉状态栏快捷设置新增选项(自动亮度&静音)_Patch 文章链接:https://blog.csdn.net/qq_33750826/article/details/122829104
前面AndroidQ SystemUI之启动 中分析了SystemUI启动过程中会加载一个config数组,里面定义了SystemUI的重要的类,之后遍历此数组,以此调用其Start方法,我们就从StatusBar.start方法开始分析锁屏相关的流程 Status...
mt6572平台,内置mp4到内置T卡。\src\com\android\systemui\statusbar\phone
icon_mobile_data_off" /> <com.android.systemui.statusbar.lonyii.MobileDataSettingButton android:textSize="1.0dip" android:textStyle="normal" android:textColor="#ffffffff" android:gravity="center_...
Android 4.4 (KitKat) introduced translucent system UI styling for status bar, then Android 5.0 offers simple ways to enable translucency in Activity( android:windowTranslucentStatus) and tint color ...
StatusBar 和 NavigationBar。 颜色是通过使 SystemUI bar(s) 变成。 SystemUI 栏变为半透明,并在其后面显示彩色View ,使其看起来有色。 由于使用系统 API 来实现此功能,大多数情况都已被漂亮的混合动画和良好的...
本文实例讲述了Android编程实现禁止状态栏...路径:==/frameworks/base/packages/SystemUI//src/com/android/systemui/statusbar/phone/PhoneStatusBar.Java== 通过在PhoneStatusBar.java类中注册一个广播的方式来实现
发布博客文章:https://pspdfkit.com/blog/2016/clean-statusbar-with-systemui-and-quickdemo/要求Android SDK(API 25)Android Studio 2.2+ adb(用于安装应用程序并授予所需的权限)Android模拟器或运行棉花糖...
Android从4.4(KitKat) 开始进行了一些视觉上的改善和提升,其中包括让状态栏(Status Bar)和下方导航栏(Navigation Bar)进行半透明处理,可以使APP内容向上下延伸,使整个画面的利用度大幅度提升,本篇就来说说这个...
状态栏-StatusBar Notifier View 状态栏之MPNotificationView Ad Controller AdMob demo Animation之Gmail Like Loading AWVersionAgent Bee Framework Circle Menu Cocoa Touch Barcodes Contact Picker FileMD5...
状态栏图标的布局文件在frameworks\base\packages\SystemUI\res\layout\status_bar.xml,主要包括通知,定位,蓝牙,信号,时间,电池等图标,只要在相应的布局文件中加入属性android:visibility=invisible 或者...
(Screen Shot) * Fully Customizable Status Bar - Need a status bar which your end-users can customize just as they do their toolbars and menus? ExpressBars includes a built-in status bar so you ...
底部的BACK HOME 还有电池WIFI的那一条STATUS_BAR设置全屏后怎么也去不掉,查找资料后,发现一个比较好的方法,在此分享 第一种方式(程序代码): 在OnCreate里添加一行语句 代码如下:getWindow().getDecorView()....