• Android 9.0系统源码_SystemUI(四)通知图标控制器


    前言

    上一篇我们具体分析了状态栏上状态图标,例如 wifi、蓝牙等图标的控制流程,本篇文章我们继续来分析下状态栏上通知图标的控制流程。主要分析当一个新通知来临时,新通知的图标是如何一步步显示到状态栏上的。

    一、通知图标控制器

    1、通过上一篇系统状态栏图标控制可知,状态栏图标是由一个叫StatusBarIconController接口控制显示的,而通知图标区域也有一个控制器,叫NotificationIconAreaController(它不是一个接口)。

    frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java

    public class NotificationIconAreaController implements DarkReceiver {
     	...
        public NotificationIconAreaController(Context context, StatusBar statusBar) {
            mStatusBar = statusBar;
            mNotificationColorUtil = NotificationColorUtil.getInstance(context);//通知栏颜色工具
            mContext = context;
            mEntryManager = Dependency.get(NotificationEntryManager.class);
    
            initializeNotificationAreaViews(context);//初始化通知栏区域视图
        }
        ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2、在NotificationIconAreaController的构造函数中会调用如下方法来创建通知图标的容器

    public class NotificationIconAreaController implements DarkReceiver {
        ...
        /**
         * 初始化化通知图标区域视图
         */
        protected void initializeNotificationAreaViews(Context context) {
            reloadDimens(context);
            LayoutInflater layoutInflater = LayoutInflater.from(context);
            // 实例化通知图标区域视图
            mNotificationIconArea = inflateIconArea(layoutInflater);
            // mNotificationIcons才是真正存放通知图标的父容器
            mNotificationIcons = (NotificationIconContainer) mNotificationIconArea.findViewById(R.id.notificationIcons);
            mNotificationScrollLayout = mStatusBar.getNotificationScrollLayout();
        }
        ...
        protected View inflateIconArea(LayoutInflater inflater) {
            // 实例化通知图标区域视图
            return inflater.inflate(R.layout.notification_icon_area, null);
        }
        ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    3、这里加载了notification_icon_are.xml布局,来看下这个布局

    frameworks/base/packages/SystemUI/res/layout/notification_icon_area.xml

    <com.android.keyguard.AlphaOptimizedLinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/notification_icon_area_inner"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipChildren="false">
        <com.android.systemui.statusbar.phone.NotificationIconContainer
            android:id="@+id/notificationIcons"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_alignParentStart="true"
            android:gravity="center_vertical"
            android:orientation="horizontal"
            android:clipChildren="false"/>
    com.android.keyguard.AlphaOptimizedLinearLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    id为notificationIcons的NotificationIconContainer就是通知图标容器,对应于上面代码的mNotificationIcons变量。

    二、初始化通知图标区域

    1、既然是NotificationIconAreaController自己创建了通知图标容器,那么通知图标是如何被添加到状态栏视图中的呢?这个动作其实是在创建状态栏视图后完成的,主要是在StatusBar的makeStatusBarView方法中。

    frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java

        protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
            ...
            // 创建状态栏视图
            FragmentHostManager.get(mStatusBarWindow)
                    .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
                        CollapsedStatusBarFragment statusBarFragment = (CollapsedStatusBarFragment) fragment;
                        // 用通知图标控制器,初始化了通知图标区域和中心图标区域,并且显示出来
                        statusBarFragment.initNotificationIconArea(mNotificationIconAreaController);
                        ...
                    }).getFragmentManager()
                    .beginTransaction()
                    // CollapsedStatusBarFragment实现了状态栏的添加
                    .replace(R.id.status_bar_container, new CollapsedStatusBarFragment(),
                            CollapsedStatusBarFragment.TAG)
                    .commit();     
          ...         
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2、调用的就是CollapsedStatusBarFragment的initNotificationIconArea()方法。

    frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java

        public void initNotificationIconArea(NotificationIconAreaController
                notificationIconAreaController) {
            // 通知图标区域
            ViewGroup notificationIconArea = mStatusBar.findViewById(R.id.notification_icon_area);
            // 这个才是通知图标的父容器
            mNotificationIconAreaInner = notificationIconAreaController.getNotificationInnerAreaView();
            if (mNotificationIconAreaInner.getParent() != null) {
                ((ViewGroup) mNotificationIconAreaInner.getParent())
                        .removeView(mNotificationIconAreaInner);
            }
            // 把通知图标父容器添加到通知图标区域里
            notificationIconArea.addView(mNotificationIconAreaInner);
            // 这里其实显示了通知图标区域和中心图标区域
            showNotificationIconArea(false);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    三、监听通知的服务端

  • 相关阅读:
    大小仅为人血细胞的1/10?揭秘纳米机器人的厉害之处
    把react元素转成dom元素
    vue+vite+ts添加eslint校验和代码提交校验
    [Linux](2)快速入门Linux基础指令
    【golang】sync包once 只执行一次代码
    Ai-WB2系列模组linux开发环境搭建
    image标签图片变形
    python自动化运维——模拟键盘鼠标重复性操作Pyautoui
    steam搬砖项目,csgo游戏搬砖熟练操作后,可以月入过万~
    Android中获取手机SIM卡的各种信息
  • 原文地址:https://blog.csdn.net/abc6368765/article/details/126305915