`
mmdev
  • 浏览: 12890918 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

android4.0 statusbar加载icon

 
阅读更多

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是以Binderkey

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,而viewIndexi对应

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文件中定义的statusbarheight

finalintheight=getStatusBarHeight();

}

//这里将所有的状态栏上的view先初始化

WindowManagerImpl.getDefault().addView(sb,lp);

}

二、PhoneStatusBar.java

publicclassPhoneStatusBarextendsStatusBar{

}

PhoneStatusBarStatusBar(extendsSystemUI)的子类,真正和StatusBarManagerService交互的实际上就是它。

对于SystemUI,首先启动的是Start();

publicvoidstart(){

……

//调用StatusBarstart方法,建立和StatusbarManagerService之间的联系

super.start();//StatusBarstart中实现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;

//显示statusbariconview

mStatusIcons=(LinearLayout)sb.findViewById(R.id.statusIcons);

//显示notificationview

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等信息的textviewandroid4.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,注意

//mContextPhoneStatusBarmContext

StatusBarIconViewview=newStatusBarIconView(mContext,slot,null);

//设置显示的icon

view.set(icon);

//添加到msim_status_bar.xml的保存iconview中去

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;

}

只有在下面这个类中才正式显示iconstatusbar

PhoneStatusBarPolicy.java

ContextPhoneStatusBarmContext

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);

}

上面的mServiceStatusBarManager,那么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时会调用StatusBarstart函数,在这里和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就是CommandQueuePhoneStatusbar中的实现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);

}

//这才正式创建StatusBarIconiconPackagePhoneStatusBar的,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;

}

}

}

最后就是调用PhoneStatusBaraddIcon。至此,就用StatusBar显示了icon

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics