StatusBar分为两个部分:一是通常在手机界面最上端的未下拉的statusbar;二是下拉状态栏,也就是扩展状态栏。
通过在实际应用中,我们可以发现,statusbar就是一个activity,那么,它的使用自然少不了和service之间的交互。
PhoneStatusBar通过IStatusBarService来访问StatusBarManagerService,而
StatusBarManagerService通过CommandQueue来和PhoneStatusBar进行交互。
一、StatusBar.java
通过classStatusBar的声明,我们可以看出,它或者其子类实现和StatusBarManagerService进行交互的CommandQueue的回调方法。
publicabstractclassStatusBarextendsSystemUIimplementsCommandQueue.Callbacks{
publicvoidstart(){
Viewsb=makeStatusBarView();
//创建包括在config.xml中定义要在statusbar上显示的所有icons,那么它包含icons个数在何处初始化?
StatusBarIconListiconList=newStatusBarIconList();
//保存Notification是以Binder为key的
ArrayList<IBinder>notificationKeys=newArrayList<IBinder>();
//保存在statusbar上显示的StatusBarNotification
ArrayList<StatusBarNotification>notifications=newArrayList<StatusBarNotification>();
//和IStatusBarService进行交互的IBinder
mCommandQueue=newCommandQueue(this,iconList);
//获取StatusBarManagerService的本地实现
mBarService=IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
int[]switches=newint[7];
ArrayList<IBinder>binders=newArrayList<IBinder>();
try{
//这一步实际上就是将PhoneStatusBar的实现的CommandQueue其中包含
//callbacks传递给StatusbarManagerService使用
mBarService.registerStatusBar(mCommandQueue,
iconList,notificationKeys,notifications,
switches,binders);
}catch(RemoteExceptionex){
//Ifthesystemprocessisn'ttherewe'redoomedanyway.
}
for(inti=0;i<N;i++){
//这里第一次使用时icon仅仅是开辟一个存储空间,i代表的是数组的index,而viewIndex和i对应
StatusBarIconicon=iconList.getIcon(i);
if(icon!=null){
addIcon①(iconList.getSlot(i),i,viewIndex,icon);
viewIndex++;
}
}
N=notificationKeys.size();
if(N==notifications.size()){
for(inti=0;i<N;i++){
addNotification②(notificationKeys.get(i),notifications.get(i));
}
}else{
}
//xml文件中定义的statusbar的height
finalintheight=getStatusBarHeight();
}
//这里将所有的状态栏上的view先初始化
WindowManagerImpl.getDefault().addView(sb,lp);
}
二、PhoneStatusBar.java
publicclassPhoneStatusBarextendsStatusBar{
}
PhoneStatusBar是StatusBar(extendsSystemUI)的子类,真正和StatusBarManagerService交互的实际上就是它。
对于SystemUI,首先启动的是Start();
publicvoidstart(){
……
//调用StatusBar的start方法,建立和StatusbarManagerService之间的联系
super.start();//在StatusBar的start中实现makeStatusBarView然后初始化statusbaricon状态
//启动更新Icon的方法
mIconPolicy=newPhoneStatusBarPolicy(mContext);
}
super.start()中我们看到,StatusBar是一个abstract类,真正要建立View是不能够的,必须在子类中创建。
实际上,StatusBar中也这样定义protectedabstractViewmakeStatusBarView()
PhoneStatusBar中:
protectedViewmakeStatusBarView(){
finalContextcontext=mContext;
Resourcesres=context.getResources();
//定义Icon的大小,缩放率和彼此间距
loadDimens();
mIconSize=
res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
//状态栏下拉时的view
ExpandedViewexpanded=(ExpandedView)View.inflate(context,
R.layout.status_bar_expanded,null);
//真正显示的statusbar是根据是否是双卡来选择xml文件
PhoneStatusBarViewsb;
if(TelephonyManager.getDefault().isMultiSimEnabled()){
sb=(PhoneStatusBarView)View.inflate(context,
R.layout.msim_status_bar,null);
}else{
sb=(PhoneStatusBarView)View.inflate(context,
R.layout.status_bar,null);
}
//获取statusbar的实例
sb.mService=this;
mStatusBarView=sb;
//显示statusbaricon的view
mStatusIcons=(LinearLayout)sb.findViewById(R.id.statusIcons);
//显示notification的view
mNotificationIcons=(IconMerger)sb.findViewById(R.id.notificationIcons);
mMoreIcon=sb.findViewById(R.id.moreIcon);
//定义下拉状态栏,显示Notifications
mExpandedDialog=newExpandedDialog(context);
/*这个expanded就是指layout下的status_bar_expanded.xml解析所得下拉状态栏*/
mExpandedView=expanded;
//显示Notification的控件,NotificationRowLayout是处理函数,
mPile=(NotificationRowLayout)expanded.findViewById(R.id.latestItems);
mExpandedContents=mPile;//was:expanded.findViewById(R.id.notificationLinearLayout);
//android2.3中显示onGoing等信息的textview,android4.0已经不用了
mNoNotificationsTitle=(TextView)expanded.findViewById(R.id.noNotificationsTitle);
mNoNotificationsTitle.setVisibility(View.GONE);
……
}
在步骤一的函数start()中的标识①处调用的是PhoneStatusBar的函数,在那里初始化statusbaricon,
前面说了,在registerStatusBar时获得的iconList是没有icon的
publicvoidaddIcon(Stringslot,intindex,intviewIndex,StatusBarIconicon){
//依据config.xml中的config_statusBarIcons定义的字符串创建StatusBarIconView,注意
//mContext是PhoneStatusBar的mContext
StatusBarIconViewview=newStatusBarIconView(mContext,slot,null);
//设置显示的icon
view.set(icon);
//添加到msim_status_bar.xml的保存icon的view中去
if(FeatureQuery.FEATURE_ANNUCIATOR_NEW_STATUSBAR_STYLE){
mStatusIcons.addView(view,viewIndex,
newLinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,mIconSize));
}else{
mStatusIcons.addView(view,viewIndex,
newLinearLayout.LayoutParams(mIconSize,mIconSize));
}
}
在PhoneStatusBar.java中用到下面这两个类
StatusBarIconsView.java
publicclassStatusBarIconViewextendsAnimatedImageView
publicStatusBarIconView(Contextcontext,Stringslot,Notificationnotification){
finalResourcesres=context.getResources();
mSlot=slot;
mNumberPain=newPaint();
mNumberPain.setTextAlign(Paint.Align.CENTER);
mNumberPain.setColor(res.getColor(R.drawable.notification_number_text_color));
mNumberPain.setAntiAlias(true);
mNotification=notification;
……
setScaleType(ImageView.ScaleType.CENTER);
}
}
由class的声明可以看出,StatusBarIconView是一个AnimatedImageView,因此,可以显示icon
publicbooleanset(StatusBarIconicon){
finalbooleaniconEquals=mIcon!=null
&&streq(mIcon.iconPackage,icon.iconPackage)
&&mIcon.iconId==icon.iconId;
finalbooleanlevelEquals=iconEquals
&&mIcon.iconLevel==icon.iconLevel;
finalbooleanvisibilityEquals=mIcon!=null
&&mIcon.visible==icon.visible;
finalbooleannumberEquals=mIcon!=null
&&mIcon.number==icon.number;
//将icon信息拷贝给mIcon
mIcon=icon.clone();
if(!iconEquals){
Drawabledrawable=getIcon(icon);
if(drawable==null){
returnfalse;
}
//下面两步就是获取drawable,然后设置到view中去
setImageDrawable(drawable);
}
}
privateDrawablegetIcon(StatusBarIconicon){
//我们在PhoneStatusBar中创建StatusBarIconView时传了mContext,因此这里getContext()
//也是PhoneStatusBar的
returngetIcon(getContext(),icon);
}
publicstaticDrawablegetIcon(Contextcontext,StatusBarIconicon){
……
try{
//获取icon
returnr.getDrawable(icon.iconId);
}catch(RuntimeExceptione){
}
returnnull;
}
只有在下面这个类中才正式显示icon在statusbar上
PhoneStatusBarPolicy.java
Context是PhoneStatusBar的mContext
publicPhoneStatusBarPolicy(Contextcontext){
//StatusBarManagerService
mService=(StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE);
mStorageManager=(StorageManager)context.getSystemService(Context.STORAGE_SERVICE);
mStorageManager.registerListener(
newcom.android.systemui.usb.StorageNotification(context));
//TTYstatus
mService.setIcon("tty",R.drawable.stat_sys_tty_mode,0,null);
//Alarmclock
mService.setIcon("alarm_clock",R.drawable.stat_sys_alarm,0,null);
mService.setIconVisibility("alarm_clock",false);
//volume
mService.setIcon("volume",R.drawable.stat_sys_ringer_silent,0,null);
mService.setIconVisibility("volume",false);
updateVolume();
//headset
mService.setIcon("headset",com.android.internal.R.drawable.stat_sys_headset,0,null);
mService.setIconVisibility("headset",false);
}
上面的mService是StatusBarManager,那么setIcon是操作如下:
StatusBarManager.java
publicvoidsetIcon(Stringslot,inticonId,inticonLevel,StringcontentDescription){
try{
//StatusBarManagerService的本地代理service
finalIStatusBarServicesvc=getService();
if(svc!=null){
svc.setIcon(slot,mContext.getPackageName(),iconId,iconLevel,
contentDescription);
}
}catch(RemoteExceptionex){
//systemprocessisdeadanyway.
thrownewRuntimeException(ex);
}
}
三、StatusBarManagerService.java
前面,我们启动PhoneStatusBar时会调用StatusBar的start函数,在这里和StatusbarManagerService
建立联系。
StatusBar.java中
mBarService.registerStatusBar(mCommandQueue,iconList,notificationKeys,notifications,
switches,binders);
publicclassStatusBarManagerServiceextendsIStatusBarService.Stub
implementsWindowManagerService.OnHardKeyboardStatusChangeListener
{
publicStatusBarManagerService(Contextcontext,WindowManagerServicewindowManager){
mContext=context;
mWindowManager=windowManager;
mWindowManager.setOnHardKeyboardStatusChangeListener(this);
finalResourcesres=context.getResources();
//这里,获取config_statusBarIcons.xm中定义的显示icon的数组
mIcons.defineSlots(res.
getStringArray(com.android.internal.R.array.config_statusBarIcons));
}
}
publicvoidregisterStatusBar(IStatusBarbar,StatusBarIconListiconList,
List<IBinder>notificationKeys,List<StatusBarNotification>notifications,
intswitches[],List<IBinder>binders){
//这个bar就是CommandQueue在PhoneStatusbar中的实现callbacks
mBar=bar;
synchronized(mIcons){
//将初始化这个service时获取的config_statusBarIcons数组中字符串保存到iconList,
//也就是传递给PhoneStatusBar使用了
iconList.copyFrom(mIcons);
}
synchronized(mNotifications){
for(Map.Entry<IBinder,StatusBarNotification>e:mNotifications.entrySet()){
notificationKeys.add(e.getKey());
notifications.add(e.getValue());
}
}
……
}
publicvoidsetIcon(Stringslot,StringiconPackage,inticonId,inticonLevel,
StringcontentDescription){
enforceStatusBar();
synchronized(mIcons){
//也就是当前这个slot在数组中的index
intindex=mIcons.getSlotIndex(slot);
//如果没有定义的slot,就报异常
if(index<0){
thrownewSecurityException("invalidstatusbariconslot:"+slot);
}
//这才正式创建StatusBarIcon,iconPackage是PhoneStatusBar的,iconId就是我们设置的
StatusBarIconicon=newStatusBarIcon(iconPackage,iconId,iconLevel,0,
contentDescription);
//数组中对应的index设置了icon
mIcons.setIcon(index,icon);
if(mBar!=null){
try{
mBar.setIcon(index,icon);
}catch(RemoteExceptionex){
}
}
}
}
CommandQueue.java
publicvoidsetIcon(intindex,StatusBarIconicon){
synchronized(mList){
//mList用的也是StatusBarManagerService中初始化的iconList
intwhat=MSG_ICON|index;
mHandler.removeMessages(what);
mHandler.obtainMessage(what,OP_SET_ICON,0,icon.clone()).sendToTarget();
}
}
privatefinalclassHextendsHandler{
publicvoidhandleMessage(Messagemsg){
finalintwhat=msg.what&MSG_MASK;
switch(what){
caseMSG_ICON:{
finalintindex=msg.what&INDEX_MASK;
finalintviewIndex=mList.getViewIndex(index);
switch(msg.arg1){
caseOP_SET_ICON:{
StatusBarIconicon=(StatusBarIcon)msg.obj;
//mList
StatusBarIconold=mList.getIcon(index);
if(old==null){
mList.setIcon(index,icon);
mCallbacks.addIcon(mList.getSlot(index),index,viewIndex,icon);
}else{
mList.setIcon(index,icon);
mCallbacks.updateIcon(mList.getSlot(index),index,viewIndex,
old,icon);
}
break;
}
}
}
最后就是调用PhoneStatusBar的addIcon。至此,就用StatusBar显示了icon
分享到:
相关推荐
打包文件中列出在Android 2.3系统的StatusBar上面添加,home,back等按钮所需要的资源文件及其一些代码Patch。
隐藏Android4.0及以上版本的ActionBar、NotificationBar、StatusBar、SystemBar、TitleBar
Android 4.0 ICS SystemUI浅析——StatusBar工作流程之时间日期设置文中涉及到的图片以及代码。 文章地址:http://blog.csdn.net/yihongyuelan
无系统权限应用使用悬浮窗起到禁用status功能bug
Android 4.0 ICS SystemUI浅析——StatusBar结构分析中所涉及到的全部图片。
matlab开发-statusbar。设置/获取GUI图形和Matlab桌面的状态栏
gm-statusbar 状态栏透明工具类
Android statusBar添加bac
autocad中statusbar的demo
VS2008中Dlg中如何添加status bar.Status bar实现示例
StatusBar DarkMode (Dark TextColor And Icon) 4.4 6.0 miui6 flyme4 Gradle dependencies{ compile 'com.android.support:support-v4:23.4.0' compile ...
Android NavigationBar隐藏与浮层,Status Bar的隐藏与浮层效果,SystemBar(Status Bar 和Navigation Bar)设置 Immersive与Sticky Immersion风格
android403隐藏statusbar.doc
本篇文章主要介绍了Android实现状态栏(statusbar)渐变效果的示例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
ANDROID状态栏的简单应用笔记,和通知的简单编程
delphi中改变statusbar的背景色和字体颜色
本文实例讲述了Android编程实现禁止StatusBar下拉的方法。分享给大家供大家参考,具体如下: Android中有许多隐藏的Service,StatusBarManager就是其中一个,在Context.java中可以看到: /** * Use with {@link #...
android403隐藏statusbar.doc
适用于Cordova> = 3.0的插件必需的Android SDK API 21安装对于科尔多瓦: cordova plugin add https://github.com/iFernandoSousa/android-statusbar-manager.git使用插件如果使用此插件,则不需要使用Cordova ...
Android-StatusBar-Manager 管理 Android 状态栏,并允许在 KITKAT 中使用 Translucent 并为 Lollipop 设置 Color 或 Transparent。 Cordova 插件 >= 3.0 必需的 Android SDK API 21 安装 科尔多瓦: cordova ...