ToB企服应用市场:ToB评测及商务社交产业平台

标题: Android SystemUI组件(05)状态栏-系统状态图标表现&管理 [打印本页]

作者: 守听    时间: 2024-11-12 21:30
标题: Android SystemUI组件(05)状态栏-系统状态图标表现&管理
该系列文章总纲链接:专题分纲目录 Android SystemUI组件

本章关键点总结 & 说明:


说明:本章节持续迭代之前章节的头脑导图,主要关注下方 SystemBars分析中状态栏中的部门-系统状态图标表现&管理 即可。
1 系统状态图标表现和管理根本解读

系统状态图标区域通常位于状态栏的右侧,表现了诸如电池电量、信号强度、Wi-Fi毗连、蓝牙状态、闹钟、自动旋转锁定等系统信息的图标。以下是对这一功能方面的团体描述:
团体而言,系统状态图标区域是Android系统中用户界面的一个重要组成部门,它为用户提供了快速查看和交互系统状态的便捷方式。
2 系统状态图标区域表现图标流程解读

这里的关键流程分析为:系统状态图标区域中表现一个图标的流程,主要分析StatusBarManager的setIcon方法实现。拆毁分成2个过程,具体如下:
2.1 从StatusBarManager的setIcon到mBar.setIcon详细解读

StatusBarManager的setIcon代码实现如下:
  1. public class StatusBarManager {
  2.     //...
  3.     private Context mContext;
  4.     private IStatusBarService mService;
  5.     private IBinder mToken = new Binder();
  6.    
  7.     //...
  8.     StatusBarManager(Context context) {
  9.         mContext = context;
  10.     }
  11.     //...
  12.     private synchronized IStatusBarService getService() {
  13.         if (mService == null) {
  14.             mService = IStatusBarService.Stub.asInterface(
  15.                     ServiceManager.getService(Context.STATUS_BAR_SERVICE));
  16.             if (mService == null) {
  17.                 Slog.w("StatusBarManager", "warning: no STATUS_BAR_SERVICE");
  18.             }
  19.         }
  20.         return mService;
  21.     }
  22.     //...
  23.     public void setIcon(String slot, int iconId, int iconLevel, String contentDescription) {
  24.         try {
  25.             final IStatusBarService svc = getService();
  26.             if (svc != null) {
  27.                 svc.setIcon(slot, mContext.getPackageName(), iconId, iconLevel,
  28.                     contentDescription);
  29.             }
  30.         } catch (RemoteException ex) {
  31.             // system process is dead anyway.
  32.             throw new RuntimeException(ex);
  33.         }
  34.     }
  35.     //...
  36. }
复制代码
这个方法的作用是将一个图标添加到状态栏的指定位置,并提供图标的资源ID和描述信息。如果调用乐成,状态栏上会在相应的位置表现这个图标。如果svc(IStatusBarService的实例)为空或者发生了远程非常(RemoteException),则表示无法与状态栏服务通讯,通常会抛出一个运行时非常。此中的4个参数解读如下:
实际上就是调用StatusBarManagerService的setIcon方法,代码具体实现为:
  1. public class StatusBarManagerService extends IStatusBarService.Stub {
  2.     private static final String TAG = "StatusBarManagerService";
  3.     //...
  4.     private NotificationDelegate mNotificationDelegate;
  5.     private volatile IStatusBar mBar;
  6.     private StatusBarIconList mIcons = new StatusBarIconList();
  7.     //...
  8.     public StatusBarManagerService(Context context, WindowManagerService windowManager) {
  9.         mContext = context;
  10.         mWindowManager = windowManager;
  11.         final Resources res = context.getResources();
  12.         mIcons.defineSlots(res.getStringArray(com.android.internal.R.array.config_statusBarIcons));
  13.         LocalServices.addService(StatusBarManagerInternal.class, mInternalService);
  14.     }
  15.     //...
  16.     @Override
  17.     public void setIcon(String slot, String iconPackage, int iconId, int iconLevel,
  18.             String contentDescription) {
  19.         //安全性检查,必须有android.permission.STATUS_BAR系统权限才能设置系统状态图标。
  20.         enforceStatusBar();
  21.         synchronized (mIcons) {
  22.             //从mIcons中获取预定义的意图索引,找不到抛异常
  23.             int index = mIcons.getSlotIndex(slot);
  24.             if (index < 0) {
  25.                 throw new SecurityException("invalid status bar icon slot: " + slot);
  26.             }
  27.             //创建StatusBarIcon对象(封装图标相关信息)
  28.             StatusBarIcon icon = new StatusBarIcon(iconPackage, UserHandle.OWNER, iconId,
  29.                     iconLevel, 0,
  30.                     contentDescription);
  31.             //这里将图标信息保存在副本中,主要用于SystemUI意外退出后恢复使用。
  32.             mIcons.setIcon(index, icon);
  33.             if (mBar != null) {
  34.                 try {
  35.                     //这里设置请求发送给BaseSstatusBar,提交到SystemUI状态栏
  36.                     mBar.setIcon(index, icon);
  37.                 } catch (RemoteException ex) {
  38.                 }
  39.             }
  40.         }
  41.     }
  42.     //...
  43. }
复制代码
接下来对mBar.setIcon的实现举行详细解读。因为这里涉及了IStatusBar,这里先简单做一个根本的解读。SystemUI是负责提供用户与系统交互界面的组件,此中包罗状态栏、关照栏、锁屏界面等。在这个上下文中,CommandQueue、StatusBarWindowView、BaseStatusBar和PhoneStatusBar是构成状态栏的关键组件。下面是它们之间的关系和作用的解读:
在Android 系统中,当系统需要更新状态栏(比方,收到新关照、信号强度变化等)时,StatusBarManagerService会通过CommandQueue发送相应的下令。CommandQueue将这些下令转发给PhoneStatusBar(BaseStatusBar的具体实现),PhoneStatusBar根据下令更新StatusBarWindowView中的内容,从而在用户设备上反映这些变化。
有了上面的基础,我们继承分析mBar.setIcon的实现。
2.2 mBar.setIcon详细解读

这里的mBar是IStatusBar范例,实际上是CommandQueue(它继承了IStatusBar.Stub)范例。因此继承分析mBar对应范例CommandQueue的setIcon方法。具体实现如下:
  1. public class CommandQueue extends IStatusBar.Stub {
  2.     private static final int INDEX_MASK = 0xffff;
  3.     private static final int MSG_SHIFT  = 16;
  4.     private static final int MSG_MASK   = 0xffff << MSG_SHIFT;
  5.     private static final int OP_SET_ICON    = 1;
  6.     private static final int OP_REMOVE_ICON = 2;
  7.     //...
  8.     public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
  9.         mCallbacks = callbacks;
  10.         mList = list;
  11.     }
  12.     public void setIcon(int index, StatusBarIcon icon) {
  13.         synchronized (mList) {
  14.             int what = MSG_ICON | index;
  15.             mHandler.removeMessages(what);
  16.             //hanlder发送消息OP_SET_ICON
  17.             mHandler.obtainMessage(what, OP_SET_ICON, 0, icon.clone()).sendToTarget();
  18.         }
  19.     }
  20.     public void removeIcon(int index) {
  21.         synchronized (mList) {
  22.             int what = MSG_ICON | index;
  23.             mHandler.removeMessages(what);
  24.             //hanlder发送消息OP_REMOVE_ICON
  25.             mHandler.obtainMessage(what, OP_REMOVE_ICON, 0, null).sendToTarget();
  26.         }
  27.     }
  28.     //...
  29.     private final class H extends Handler {
  30.         public void handleMessage(Message msg) {
  31.             final int what = msg.what & MSG_MASK;
  32.             switch (what) {
  33.                 case MSG_ICON: {
  34.                     final int index = msg.what & INDEX_MASK;
  35.                     final int viewIndex = mList.getViewIndex(index);
  36.                     switch (msg.arg1) {
  37.                         case OP_SET_ICON: {//处理消息OP_SET_ICON
  38.                             StatusBarIcon icon = (StatusBarIcon)msg.obj;
  39.                             StatusBarIcon old = mList.getIcon(index);
  40.                            
  41.                             if (old == null) {//不存在则添加图标
  42.                                 mList.setIcon(index, icon);
  43.                                 //这里的mCallbacks是初始化时传递进来的,实际上就是PhoneStatusBar
  44.                                 mCallbacks.addIcon(mList.getSlot(index), index, viewIndex, icon);
  45.                             } else {//存在则更新图标
  46.                                 mList.setIcon(index, icon);
  47.                                 mCallbacks.updateIcon(mList.getSlot(index), index, viewIndex,
  48.                                         old, icon);
  49.                             }
  50.                             break;
  51.                         }
  52.                         case OP_REMOVE_ICON:
  53.                             if (mList.getIcon(index) != null) {
  54.                                 mList.removeIcon(index);
  55.                                 //这里的mCallbacks是初始化时传递进来的,实际上就是PhoneStatusBar
  56.                                 mCallbacks.removeIcon(mList.getSlot(index), index, viewIndex);
  57.                             }
  58.                             break;
  59.                     }
  60.                     break;
  61.                 }
  62.                 //...
  63.             }
  64.         }
  65.     }
  66.     //...
  67. }
复制代码
接下来我们对mCallbacks部门举行简单解读,实际上就是PhoneStatusBar在构造函数阶段初始化时传递给CommandQueue。而PhoneStatusBar又是继承自BaseStatusBar的,BaseStatusBar代码实现如下:
  1. public abstract class BaseStatusBar extends SystemUI implements
  2.         CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
  3.         RecentsComponent.Callbacks, ExpandableNotificationRow.ExpansionLogger,
  4.         NotificationData.Environment {
  5.     public static final String TAG = "StatusBar";
  6.     public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
  7.     public static final boolean MULTIUSER_DEBUG = false;
  8.     public void start() {
  9.         //...
  10.         // Connect in to the status bar manager service
  11.         StatusBarIconList iconList = new StatusBarIconList();
  12.         //这里初始化CommandQueue时传入的实际山是PhoneStatusBar
  13.         mCommandQueue = new CommandQueue(this, iconList);
  14.         //...
  15.     }
  16.     //...
  17. }
复制代码
接下来继承看PhoneStatusBar的实现与对setIcon的分别处理(addIcon和updateIcon),代码实现如下:
  1. public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
  2.         DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener {
  3.     static final String TAG = "PhoneStatusBar";
  4.     public static final boolean DEBUG = BaseStatusBar.DEBUG;
  5.     public static final boolean SPEW = false;
  6.     public static final boolean DUMPTRUCK = true; // extra dumpsys info
  7.     public static final boolean DEBUG_GESTURES = false;
  8.     public static final boolean DEBUG_MEDIA = false;
  9.     public static final boolean DEBUG_MEDIA_FAKE_ARTWORK = false;
  10.     //...
  11.     public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
  12.         StatusBarIconView view = new StatusBarIconView(mContext, slot, null);
  13.         view.set(icon);
  14.         mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(
  15.                 LayoutParams.WRAP_CONTENT, mIconSize));
  16.         view = new StatusBarIconView(mContext, slot, null);
  17.         view.set(icon);
  18.         mStatusIconsKeyguard.addView(view, viewIndex, new LinearLayout.LayoutParams(
  19.                 LayoutParams.WRAP_CONTENT, mIconSize));
  20.     }
  21.     public void updateIcon(String slot, int index, int viewIndex,
  22.             StatusBarIcon old, StatusBarIcon icon) {
  23.         StatusBarIconView view = (StatusBarIconView) mStatusIcons.getChildAt(viewIndex);
  24.         view.set(icon);
  25.         view = (StatusBarIconView) mStatusIconsKeyguard.getChildAt(viewIndex);
  26.         view.set(icon);
  27.     }
  28.     public void removeIcon(String slot, int index, int viewIndex) {
  29.         mStatusIcons.removeViewAt(viewIndex);
  30.         mStatusIconsKeyguard.removeViewAt(viewIndex);
  31.     }
  32.     //...
  33. }
复制代码
至此,关键代码的流程就分析竣事了。总结下:


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4