1.改变通知栏右上角状态图标流程。(Leadcore代码)
android.app.StatusBarManager定义了操作通知栏的方法,比如展开、收缩通知栏,修改、移除、隐藏通知栏状态图片、屏蔽虚拟按键,这是个hide类,通过远程调用StatusBarManagerService实现功能。
StatusBarManagerService中对能替换的图标进行了限制,具体限制列表如下
<string-array name="config_statusBarIcons">
<item><xliff:g id="id">ime</xliff:g></item>
<item><xliff:g id="id">sync_failing</xliff:g></item>
<item><xliff:g id="id">sync_active</xliff:g></item>
<item><xliff:g id="id">location</xliff:g></item>
<item><xliff:g id="id">bluetooth</xliff:g></item>
<item><xliff:g id="id">nfc</xliff:g></item>
<item><xliff:g id="id">tty</xliff:g></item>
<item><xliff:g id="id">speakerphone</xliff:g></item>
<item><xliff:g id="id">mute</xliff:g></item>
<item><xliff:g id="id">volume</xliff:g></item>
<item><xliff:g id="id">wifi</xliff:g></item>
<item><xliff:g id="id">cdma_eri</xliff:g></item>
<item><xliff:g id="id">data_connection</xliff:g></item>
<item><xliff:g id="id">phone_evdo_signal</xliff:g></item>
<item><xliff:g id="id">phone_signal</xliff:g></item>
<item><xliff:g id="id">battery</xliff:g></item>
<item><xliff:g id="id">alarm_clock</xliff:g></item>
<item><xliff:g id="id">secure</xliff:g></item>
<item><xliff:g id="id">clock</xliff:g></item>
<item><xliff:g id="id">headset</xliff:g></item>
<item><xliff:g id="id">phonemode</xliff:g></item>
<item><xliff:g id="id">faxswitch</xliff:g></item>
</string-array>
以setIcon(String slot, int iconId, int iconLevel, String contentDescription) 方法为例,slot只能是上面定义中的一个。
在StatusBarManagerService中又调用了IStatusBar接口的setIcon(index, icon)方法
public void setIcon(String slot, String iconPackage, int iconId, int iconLevel,
String contentDescription) {
enforceStatusBar();
synchronized (mIcons) {
int index = mIcons.getSlotIndex(slot);
if (index < 0) {
throw new SecurityException("invalid status bar icon slot: " + slot);
}
StatusBarIcon icon = new StatusBarIcon(iconPackage, UserHandle.OWNER, iconId,
iconLevel, 0,
contentDescription);
//Slog.d(TAG, "setIcon slot=" + slot + " index=" + index + " icon=" + icon);
mIcons.setIcon(index, icon);
if (mBar != null) {
try {
mBar.setIcon(index, icon);
} catch (RemoteException ex) {
}
}
}
}
IStatusBar是通过registerStatusBar传递进来,registerStatusBar是在 com.android.systemui.statusbar.BaseStatusBar的start()方法中调用
mCommandQueue = new CommandQueue(this, iconList);
int[] switches = new int[7];
ArrayList<IBinder> binders = new ArrayList<IBinder>();
try {
mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications,
switches, binders);
} catch (RemoteException ex) {
// If the system process isn't there we're doomed anyway.
}
为CommandQueue对象。
在CommandQueue中通过handler处理what消息为MSG_ICON,msg.arg1为OP_SET_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;
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);
mCallbacks.updateIcon(mList.getSlot(index), index, viewIndex,
old, icon);
}
break;
}
mCallbacks是CommandQueue构造时的第一个参数,也就是BaseStatusBar.this,BaseStatusBar是个抽象类,其实现类为com.android.systemui.statusbar.phone.PhoneStatusBar
public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
if (SPEW) Log.d(TAG, "addIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
+ " icon=" + icon);
StatusBarIconView view = new StatusBarIconView(mContext, slot, null);
view.set(icon);
mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(mIconSize, mIconSize));
}
public void updateIcon(String slot, int index, int viewIndex,
StatusBarIcon old, StatusBarIcon icon) {
if (SPEW) Log.d(TAG, "updateIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
+ " old=" + old + " icon=" + icon);
StatusBarIconView view = (StatusBarIconView)mStatusIcons.getChildAt(viewIndex);
view.set(icon);
}
public void removeIcon(String slot, int index, int viewIndex) {
if (SPEW) Log.d(TAG, "removeIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex);
mStatusIcons.removeViewAt(viewIndex);
}
以上流程必须在SystemUi启动后才能调用,也就是PhoneStatusBar的start方法被调用后。