android4.0 statusbar加载icon
6302 点击·0 回帖
![]() | ![]() | |
![]() | StatusBar分为两个部分:一是通常在手机界面最上端的未下拉的statusbar;二是下拉状态栏,也就是扩展状态栏。 通过在实际应用中,我们可以发现,statusbar就是一个activity,那么,它的使用自然少不了和service之间的交互。 PhoneStatusBar 通过IStatusBarService来访问StatusBarManagerService,而 StatusBarManagerService通过CommandQueue来和PhoneStatusBar进行交互。 一、StatusBar.java 通过class StatusBar的声明,我们可以看出,它或者其子类实现和StatusBarManagerService进行交互的CommandQueue的回调方法。 public abstract class StatusBar extends SystemUI implements CommandQueue.Callbacks { public void start() { View sb = makeStatusBarView(); //创建包括在config.xml中定义要在statusbar上显示的所有icons,那么它包含icons个数在何处初始化? StatusBarIconList iconList = new StatusBarIconList(); //保存Notification是以Binder为key的 ArrayList<IBinder> notificationKeys = new ArrayList<IBinder>(); //保存在statusbar上显示的StatusBarNotification ArrayList<StatusBarNotification> notifications = new ArrayList<StatusBarNotification>(); //和IStatusBarService进行交互的IBinder mCommandQueue = new CommandQueue(this, iconList); //获取StatusBarManagerService的本地实现 mBarService = IStatusBarService.Stub.asinterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE)); int[] switches = new int[7]; ArrayList<IBinder> binders = new ArrayList<IBinder>(); try { //这一步实际上就是将PhoneStatusBar的实现的CommandQueue其中包含 //callbacks传递给StatusbarManagerService使用 mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications, switches, binders); } catch (RemoteException ex) { // If the system process isn't there we're doomed anyway. } for (int i=0; i<N; i++) { //这里第一次使用时icon仅仅是开辟一个存储空间,i代表的是数组的index,而viewIndex和i对应 StatusBarIcon icon = iconList.getIcon(i); if (icon != null) { addIcon①(iconList.getSlot(i), i, viewIndex, icon); viewIndex++; } } N = notificationKeys.size(); if (N == notifications.size()) { for (int i=0; i<N; i++) { addNotification②(notificationKeys.get(i), notifications.get(i)); } } else { } //xml文件中定义的statusbar的height final int height = getStatusBarHeight(); } //这里将所有的状态栏上的view先初始化 WindowManagerImpl.getDefault().addView(sb, lp); } 二、PhoneStatusBar.java public class PhoneStatusBar extends StatusBar { } PhoneStatusBar 是StatusBar(extends SystemUI)的子类,真正和StatusBarManagerService交互的实际上就是它。 对于SystemUI,首先启动的是Start(); public void start() { …… //调用StatusBar 的start方法,建立和StatusbarManagerService之间的联系 super.start();//在StatusBar的start中实现makeStatusBarView然后初始化statusbar icon状态 //启动更新Icon的方法 mIconPolicy = new PhoneStatusBarPolicy(mContext); } super.start()中我们看到,StatusBar是一个abstract类,真正要建立View是不能够的,必须在子类中创建。 实际上,StatusBar中也这样定义protected abstract View makeStatusBarView() PhoneStatusBar 中: protected View makeStatusBarView() { final Context context = mContext; Resources res = context.getResources(); //定义Icon的大小,缩放率和彼此间距 loadDimens(); mIconSize = res.getDimensionPixelSize(com.Android.internal.R.dimen.status_bar_icon_size); //状态栏下拉时的view ExpandedView expanded = (ExpandedView)View.inflate(context, R.layout.status_bar_expanded, null); //真正显示的statusbar是根据是否是双卡来选择xml文件 PhoneStatusBarView sb; 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; //显示statusbar icon的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 = new ExpandedDialog(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的函数,在那里初始化status bar icon, 前面说了,在registerStatusBar时获得的iconList是没有icon的 public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) { //依据config.xml中的config_statusBarIcons定义的字符串创建StatusBarIconView,注意 //mContext是PhoneStatusBar的mContext StatusBarIconView view = new StatusBarIconView(mContext, slot, null); //设置显示的icon view.set(icon); //添加到msim_status_bar.xml的保存icon的view中去 if (FeatureQuery.FEATURE_ANNUCIATOR_NEW_STATUSBAR_STYLE) { mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, mIconSize)); } else { mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(mIconSize, mIconSize)); } } 在PhoneStatusBar.java中用到下面这两个类 StatusBarIconsView.java public class StatusBarIconView extends AnimatedImageView public StatusBarIconView(Context context, String slot, Notification notification) { final Resources res = context.getResources(); mSlot = slot; mNumberPain = new Paint(); 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 public boolean set(StatusBarIcon icon) { final boolean iconEquals = mIcon != null ;; streq(mIcon.iconPackage, icon.iconPackage) ;; mIcon.iconId == icon.iconId; final boolean levelEquals = iconEquals ;; mIcon.iconLevel == icon.iconLevel; final boolean visibilityEquals = mIcon != null ;; mIcon.visible == icon.visible; final boolean numberEquals = mIcon != null ;; mIcon.number == icon.number; //将icon信息拷贝给mIcon mIcon = icon.clone(); if (!iconEquals) { Drawable drawable = getIcon(icon); if (drawable == null) { return false; } //下面两步就是获取drawable,然后设置到view中去 setImageDrawable(drawable); } } private Drawable getIcon(StatusBarIcon icon) { //我们在PhoneStatusBar中创建StatusBarIconView时传了mContext,因此这里getContext() //也是PhoneStatusBar的 return getIcon(getContext(), icon); } public static Drawable getIcon(Context context, StatusBarIcon icon) { …… try { //获取icon return r.getDrawable(icon.iconId); } catch (RuntimeException e) { } return null; } 只有在下面这个类中才正式显示icon在statusbar上 PhoneStatusBarPolicy.java Context是PhoneStatusBar的mContext public PhoneStatusBarPolicy(Context context) { //StatusBarManagerService mService = (StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE); mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE); mStorageManager.registerListener( new com.Android.systemui.usb.StorageNotification(context)); // TTY status mService.setIcon("tty", R.drawable.stat_sys_tty_mode, 0, null); // Alarm clock 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 public void setIcon(String slot, int iconId, int iconLevel, String contentDescription) { try { //StatusBarManagerService的本地代理service final IStatusBarService svc = getService(); if (svc != null) { svc.setIcon(slot, mContext.getPackageName(), iconId, iconLevel, contentDescription); } } catch (RemoteException ex) { // system process is dead anyway. throw new RuntimeException(ex); } } 三、StatusBarManagerService.java 前面,我们启动PhoneStatusBar时会调用StatusBar的start函数,在这里和StatusbarManagerService 建立联系。 StatusBar.java中 mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications, switches, binders); public class StatusBarManagerService extends IStatusBarService.Stub implements WindowManagerService.OnHardKeyboardStatusChangeListener { public StatusBarManagerService(Context context, WindowManagerService windowManager) { mContext = context; mWindowManager = windowManager; mWindowManager.setOnHardKeyboardStatusChangeListener(this); final Resources res = context.getResources(); //这里,获取config_statusBarIcons.xm中定义的显示icon的数组 mIcons.defineSlots(res. getStringArray(com.Android.internal.R.array.config_statusBarIcons)); } } public void registerStatusBar(IStatusBar bar, StatusBarIconList iconList, List<IBinder> notificationKeys, List<StatusBarNotification> notifications, int switches[], 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()); } } …… } public void setIcon(String slot, String iconPackage, int iconId, int iconLevel, String contentDescription) { enforceStatusBar(); synchronized (mIcons) { //也就是当前这个slot在数组中的index int index = mIcons.getSlotIndex(slot); //如果没有定义的slot,就报异常 if (index < 0) { throw new SecurityException("invalid status bar icon slot: " + slot); } //这才正式创建StatusBarIcon,iconPackage是PhoneStatusBar的,iconId就是我们设置的 StatusBarIcon icon = new StatusBarIcon(iconPackage, iconId, iconLevel, 0, contentDescription); //数组中对应的index设置了icon mIcons.setIcon(index, icon); if (mBar != null) { try { mBar.setIcon(index, icon); } catch (RemoteException ex) { } } } } CommandQueue.java public void setIcon(int index, StatusBarIcon icon) { synchronized (mList) { //mList用的也是StatusBarManagerService中初始化的iconList int what = MSG_ICON | index; mHandler.removeMessages(what); mHandler.obtainMessage(what, OP_SET_ICON, 0, icon.clone()).sendToTarget(); } } private final class H extends Handler { public void handleMessage(Message msg) { final int what = msg.what ; MSG_MASK; switch (what) { case MSG_ICON: { final int index = msg.what ; INDEX_MASK; final int viewIndex = mList.getViewIndex(index); switch (msg.arg1) { case OP_SET_ICON: { StatusBarIcon icon = (StatusBarIcon)msg.obj; //mList StatusBarIcon old = mList.getIcon(index); if (old == null) { mList.setIcon(index, icon); mCallbacks.addIcon(mList.getSlot(index), index, viewIndex, icon); } else { mList.setIcon(index, icon); www.atcpu.com mCallbacks.updateIcon(mList.getSlot(index), index, viewIndex, old, icon); } break; 作者:kakaBack } } } 最后就是调用PhoneStatusBar的addIcon。至此,就用StatusBar显示了icon | |
![]() | ![]() |