该系列文章总纲链接:专题分纲目录 Android SystemUI组件
本章关键点总结 & 说明:
说明:本章节持续迭代之前章节的头脑导图,主要关注下方 SystemBars分析中状态栏中的部门-系统状态图标表现&管理 即可。
1 系统状态图标表现和管理根本解读
系统状态图标区域通常位于状态栏的右侧,表现了诸如电池电量、信号强度、Wi-Fi毗连、蓝牙状态、闹钟、自动旋转锁定等系统信息的图标。以下是对这一功能方面的团体描述:
- 状态栏的构成:状态栏通常位于屏幕的顶部,是一个水平的条状区域。它包罗系统状态图标区域和关照图标区域。系统状态图标区域表现了各种系统状态信息,而关照图标区域则表现了应用程序的关照。
- 系统状态图标的表现:每个系统状态图标都代表了一个特定的系统状态或功能。图标通常会根据其代表的状态变化而变化,比方,当手机毗连到Wi-Fi网络时,Wi-Fi图标会表现为激活状态。某些图标可能会有多种状态,比方电池图标会根据电量的多少表现不同的充电状态。
- 图标的交互:用户可以通过点击某些图标来打开相干的设置界面,比方点击音量图标可能会打开音量调节滑块。长按某些图标可能会触发特定的操纵或表现更多的选项,比方长按Wi-Fi图标可能会表现可用的Wi-Fi网络列表。
- 状态栏的自界说:用户可以在系统设置中对状态栏的某些方面举行自界说,好比选择表现或隐蔽某些图标。一些制造商可能还会提供额外的自界说选项,如改变状态栏的透明度或颜色。
- 多用户和多任务处理:在多用户情况中,状态栏可能会表现与当前活跃用户相干的信息。在多任务处理时,状态栏可以提供快速切换最近使用应用的入口。
- 系统状态图标的更新:当系统状态发生变化时(如毗连到新的Wi-Fi网络),状态栏会自动更新相应的图标。系统状态图标的更新通常是由系统服务如StatusBarManagerService通过SystemUI来实现的。
- 锁屏状态下的状态栏:在锁屏状态下,状态栏可能会表现简化的信息,或者根据安全策略隐蔽某些敏感信息。
- 沉醉式体验:在某些全屏应用中,状态栏可能会被隐蔽,以提供更加沉醉式的用户体验。
团体而言,系统状态图标区域是Android系统中用户界面的一个重要组成部门,它为用户提供了快速查看和交互系统状态的便捷方式。
2 系统状态图标区域表现图标流程解读
这里的关键流程分析为:系统状态图标区域中表现一个图标的流程,主要分析StatusBarManager的setIcon方法实现。拆毁分成2个过程,具体如下:
2.1 从StatusBarManager的setIcon到mBar.setIcon详细解读
StatusBarManager的setIcon代码实现如下:
- public class StatusBarManager {
- //...
- private Context mContext;
- private IStatusBarService mService;
- private IBinder mToken = new Binder();
-
- //...
- StatusBarManager(Context context) {
- mContext = context;
- }
- //...
- private synchronized IStatusBarService getService() {
- if (mService == null) {
- mService = IStatusBarService.Stub.asInterface(
- ServiceManager.getService(Context.STATUS_BAR_SERVICE));
- if (mService == null) {
- Slog.w("StatusBarManager", "warning: no STATUS_BAR_SERVICE");
- }
- }
- return mService;
- }
- //...
- public void setIcon(String slot, int iconId, int iconLevel, String contentDescription) {
- try {
- 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);
- }
- }
- //...
- }
复制代码 这个方法的作用是将一个图标添加到状态栏的指定位置,并提供图标的资源ID和描述信息。如果调用乐成,状态栏上会在相应的位置表现这个图标。如果svc(IStatusBarService的实例)为空或者发生了远程非常(RemoteException),则表示无法与状态栏服务通讯,通常会抛出一个运行时非常。此中的4个参数解读如下:
- slot:这是一个字符串参数,代表了图标在状态栏中的位置或者"插槽"。状态栏可以有多个如许的"插槽"来表现不同的图标,好比信号强度、电池电量、Wi-Fi毗连等。开辟者可以通过指定不同的slot来控制图标在状态栏中的具体位置。
- iconId:这是一个整型参数,代表了要表现的图标资源的ID。它在config_statusBarIcons所预界说的意图列表之中。这个ID通常指向应用程序的资源文件中的一个图标。比方,如果你有一个表示Wi-Fi毗连状态的图标,它可能在资源文件中有一个唯一的ID。
- iconLevel:这个整型参数通常用于表示图标的状态或者级别。比方,电池电量图标可能会使用不同的iconLevel来表示不同的电量状态。在某些情况下,这个参数可能不被使用,具体取决于图标的范例和状态栏的实现。
- contentDescription:这是一个字符串参数,为图标提供了内容描述。这对于辅助功能(如屏幕阅读器)非常重要,因为它们可以使用这个描述来向用户报告图标的寄义。比方,如果图标表示Wi-Fi毗连,contentDescription可能会设置为"Wi-Fi毗连"。
实际上就是调用StatusBarManagerService的setIcon方法,代码具体实现为:
- public class StatusBarManagerService extends IStatusBarService.Stub {
- private static final String TAG = "StatusBarManagerService";
- //...
- private NotificationDelegate mNotificationDelegate;
- private volatile IStatusBar mBar;
- private StatusBarIconList mIcons = new StatusBarIconList();
- //...
- public StatusBarManagerService(Context context, WindowManagerService windowManager) {
- mContext = context;
- mWindowManager = windowManager;
- final Resources res = context.getResources();
- mIcons.defineSlots(res.getStringArray(com.android.internal.R.array.config_statusBarIcons));
- LocalServices.addService(StatusBarManagerInternal.class, mInternalService);
- }
- //...
- @Override
- public void setIcon(String slot, String iconPackage, int iconId, int iconLevel,
- String contentDescription) {
- //安全性检查,必须有android.permission.STATUS_BAR系统权限才能设置系统状态图标。
- enforceStatusBar();
- synchronized (mIcons) {
- //从mIcons中获取预定义的意图索引,找不到抛异常
- int index = mIcons.getSlotIndex(slot);
- if (index < 0) {
- throw new SecurityException("invalid status bar icon slot: " + slot);
- }
- //创建StatusBarIcon对象(封装图标相关信息)
- StatusBarIcon icon = new StatusBarIcon(iconPackage, UserHandle.OWNER, iconId,
- iconLevel, 0,
- contentDescription);
- //这里将图标信息保存在副本中,主要用于SystemUI意外退出后恢复使用。
- mIcons.setIcon(index, icon);
- if (mBar != null) {
- try {
- //这里设置请求发送给BaseSstatusBar,提交到SystemUI状态栏
- mBar.setIcon(index, icon);
- } catch (RemoteException ex) {
- }
- }
- }
- }
- //...
- }
复制代码 接下来对mBar.setIcon的实现举行详细解读。因为这里涉及了IStatusBar,这里先简单做一个根本的解读。SystemUI是负责提供用户与系统交互界面的组件,此中包罗状态栏、关照栏、锁屏界面等。在这个上下文中,CommandQueue、StatusBarWindowView、BaseStatusBar和PhoneStatusBar是构成状态栏的关键组件。下面是它们之间的关系和作用的解读:
- BaseStatusBar:BaseStatusBar是一个抽象类,它界说了状态栏的根本接口和一些共用的逻辑。它作为状态栏的焦点,处理与状态栏相干的各种事件和请求,好比图标的更新、关照的表现等。它实现了CommandQueue.Callbacks接口,这意味着它可以吸收来自CommandQueue的下令并作出相应。
- PhoneStatusBar:PhoneStatusBar是BaseStatusBar的具体实现,它针对手机设备(而不是平板电脑)提供了状态栏的具体逻辑和UI实现。它负责创建和管理状态栏的视图,包罗初始化状态栏的结构、处理用户交互(如下拉关照栏)、更新系统图标等。PhoneStatusBar在启动时会创建CommandQueue的实例,并将自己设置为下令的回调对象。
- CommandQueue:CommandQueue继承了IStatusBar.Stub,它作为状态栏与其他系统服务(如StatusBarManagerService)通讯的桥梁。它吸收来自系统服务的下令,并将这些下令分发到BaseStatusBar的实现(在这个场景中是PhoneStatusBar)。CommandQueue还持有一个StatusBarIconList的引用,用于管理状态栏图标的状态。
- StatusBarWindowView:StatusBarWindowView是状态栏窗口的根视图组件,它是所有状态栏UI元素的容器。这个视图在PhoneStatusBar的makeStatusBarView()方法中被创建和初始化,它包罗了状态栏的结构和子视图,如时钟、电池图标、信号强度指示器等。StatusBarWindowView负责在屏幕上表现状态栏,并且相应系统主题的变化(如深色模式)。
在Android 系统中,当系统需要更新状态栏(比方,收到新关照、信号强度变化等)时,StatusBarManagerService会通过CommandQueue发送相应的下令。CommandQueue将这些下令转发给PhoneStatusBar(BaseStatusBar的具体实现),PhoneStatusBar根据下令更新StatusBarWindowView中的内容,从而在用户设备上反映这些变化。
有了上面的基础,我们继承分析mBar.setIcon的实现。
2.2 mBar.setIcon详细解读
这里的mBar是IStatusBar范例,实际上是CommandQueue(它继承了IStatusBar.Stub)范例。因此继承分析mBar对应范例CommandQueue的setIcon方法。具体实现如下:
- public class CommandQueue extends IStatusBar.Stub {
- private static final int INDEX_MASK = 0xffff;
- private static final int MSG_SHIFT = 16;
- private static final int MSG_MASK = 0xffff << MSG_SHIFT;
- private static final int OP_SET_ICON = 1;
- private static final int OP_REMOVE_ICON = 2;
- //...
- public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
- mCallbacks = callbacks;
- mList = list;
- }
- public void setIcon(int index, StatusBarIcon icon) {
- synchronized (mList) {
- int what = MSG_ICON | index;
- mHandler.removeMessages(what);
- //hanlder发送消息OP_SET_ICON
- mHandler.obtainMessage(what, OP_SET_ICON, 0, icon.clone()).sendToTarget();
- }
- }
- public void removeIcon(int index) {
- synchronized (mList) {
- int what = MSG_ICON | index;
- mHandler.removeMessages(what);
- //hanlder发送消息OP_REMOVE_ICON
- mHandler.obtainMessage(what, OP_REMOVE_ICON, 0, null).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: {//处理消息OP_SET_ICON
- StatusBarIcon icon = (StatusBarIcon)msg.obj;
- StatusBarIcon old = mList.getIcon(index);
-
- if (old == null) {//不存在则添加图标
- mList.setIcon(index, icon);
- //这里的mCallbacks是初始化时传递进来的,实际上就是PhoneStatusBar
- mCallbacks.addIcon(mList.getSlot(index), index, viewIndex, icon);
- } else {//存在则更新图标
- mList.setIcon(index, icon);
- mCallbacks.updateIcon(mList.getSlot(index), index, viewIndex,
- old, icon);
- }
- break;
- }
- case OP_REMOVE_ICON:
- if (mList.getIcon(index) != null) {
- mList.removeIcon(index);
- //这里的mCallbacks是初始化时传递进来的,实际上就是PhoneStatusBar
- mCallbacks.removeIcon(mList.getSlot(index), index, viewIndex);
- }
- break;
- }
- break;
- }
- //...
- }
- }
- }
- //...
- }
复制代码 接下来我们对mCallbacks部门举行简单解读,实际上就是PhoneStatusBar在构造函数阶段初始化时传递给CommandQueue。而PhoneStatusBar又是继承自BaseStatusBar的,BaseStatusBar代码实现如下:
- public abstract class BaseStatusBar extends SystemUI implements
- CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
- RecentsComponent.Callbacks, ExpandableNotificationRow.ExpansionLogger,
- NotificationData.Environment {
- public static final String TAG = "StatusBar";
- public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- public static final boolean MULTIUSER_DEBUG = false;
- public void start() {
- //...
- // Connect in to the status bar manager service
- StatusBarIconList iconList = new StatusBarIconList();
- //这里初始化CommandQueue时传入的实际山是PhoneStatusBar
- mCommandQueue = new CommandQueue(this, iconList);
- //...
- }
- //...
- }
复制代码 接下来继承看PhoneStatusBar的实现与对setIcon的分别处理(addIcon和updateIcon),代码实现如下:
- public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
- DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener {
- static final String TAG = "PhoneStatusBar";
- public static final boolean DEBUG = BaseStatusBar.DEBUG;
- public static final boolean SPEW = false;
- public static final boolean DUMPTRUCK = true; // extra dumpsys info
- public static final boolean DEBUG_GESTURES = false;
- public static final boolean DEBUG_MEDIA = false;
- public static final boolean DEBUG_MEDIA_FAKE_ARTWORK = false;
- //...
- public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
- StatusBarIconView view = new StatusBarIconView(mContext, slot, null);
- view.set(icon);
- mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(
- LayoutParams.WRAP_CONTENT, mIconSize));
- view = new StatusBarIconView(mContext, slot, null);
- view.set(icon);
- mStatusIconsKeyguard.addView(view, viewIndex, new LinearLayout.LayoutParams(
- LayoutParams.WRAP_CONTENT, mIconSize));
- }
- public void updateIcon(String slot, int index, int viewIndex,
- StatusBarIcon old, StatusBarIcon icon) {
- StatusBarIconView view = (StatusBarIconView) mStatusIcons.getChildAt(viewIndex);
- view.set(icon);
- view = (StatusBarIconView) mStatusIconsKeyguard.getChildAt(viewIndex);
- view.set(icon);
- }
- public void removeIcon(String slot, int index, int viewIndex) {
- mStatusIcons.removeViewAt(viewIndex);
- mStatusIconsKeyguard.removeViewAt(viewIndex);
- }
- //...
- }
复制代码 至此,关键代码的流程就分析竣事了。总结下:
- BaseStatusBar界说了状态栏的根本举动。
- PhoneStatusBar提供了这些举动的具体实现。
- CommandQueue处理来自系统服务的下令。
- StatusBarWindowView则是状态栏UI的展示层。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |