灯火互联
管理员
管理员
  • 注册日期2011-07-27
  • 发帖数41778
  • QQ
  • 火币41290枚
  • 粉丝1086
  • 关注100
  • 终身成就奖
  • 最爱沙发
  • 忠实会员
  • 灌水天才奖
  • 贴图大师奖
  • 原创先锋奖
  • 特殊贡献奖
  • 宣传大使奖
  • 优秀斑竹奖
  • 社区明星
阅读:5524回复:0

android4.0 statusbar加载icon

楼主#
更多 发布于:2012-09-06 14:06


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

喜欢0 评分0
游客

返回顶部