Android 状态栏WiFi图标的显示逻辑

news2024/11/22 16:43:25

1. 状态栏信号图标


1.1 WIFI信号显示


WIFI信号在状态栏的显示如下图所示

当WiFi状态为关闭时,状态栏不会有任何显示。当WiFi状态打开时,会如上图所示,左侧表示有可用WiFi,右侧表示当前WiFi打开但未连接。

当WiFi状态连接时,会如上图所示,显示信号连接强度和数据连接状态。

1.2 图标更新流程框架


如图所示,WiFi图标的显示流程主要是通过监听系统的WiFi状态,然后通知UI去实时的刷新图标资源。NetworkControllerImpl.java 继承 BroadcastReceiver 监听系统WiFi状态的变化。

2. WIFI图标更新流介绍

2.1 重要类

frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\connectivity\NetworkControllerImpl.java
定义相关函数,继承BroadcastReceiver监听系统广播,动态注册广播接收器。是状态栏WiFi图标更新的核心类。
frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\connectivity\WifiIcons.java
定义了 Wifi 信号更新所需的图标资源。
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java

frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\connectivity\WifiSignalController.java

2.2 WIFI图标更新流程


(1)WifiNetworkController实例化,在NetworkControllerImpl.java进行实例化

frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\connectivity\NetworkControllerImpl.java

    @VisibleForTesting
    NetworkControllerImpl(Context context, ConnectivityManager connectivityManager,
            TelephonyManager telephonyManager,
            TelephonyListenerManager telephonyListenerManager,
            WifiManager wifiManager,
            SubscriptionManager subManager,
            Config config,
            Looper bgLooper,
            Executor bgExecutor,
            CallbackHandler callbackHandler,
            AccessPointControllerImpl accessPointController,
            StatusBarPipelineFlags statusBarPipelineFlags,
            DataUsageController dataUsageController,
            SubscriptionDefaults defaultsHandler,
            DeviceProvisionedController deviceProvisionedController,
            BroadcastDispatcher broadcastDispatcher,
            UserTracker userTracker,
            DemoModeController demoModeController,
            CarrierConfigTracker carrierConfigTracker,
            WifiStatusTrackerFactory trackerFactory,
            MobileSignalControllerFactory mobileFactory,
            @Main Handler handler,
            DumpManager dumpManager,
            LogBuffer logBuffer
    ) {
        mContext = context;
        mTelephonyListenerManager = telephonyListenerManager;
        mConfig = config;
        mMainHandler = handler;
        mReceiverHandler = new Handler(bgLooper);
        mBgLooper = bgLooper;
        mBgExecutor = bgExecutor;
        mCallbackHandler = callbackHandler;
        mStatusBarPipelineFlags = statusBarPipelineFlags;
        mDataSaverController = new DataSaverControllerImpl(context);
        mBroadcastDispatcher = broadcastDispatcher;
        mMobileFactory = mobileFactory;

        mSubscriptionManager = subManager;
        mSubDefaults = defaultsHandler;
        mConnectivityManager = connectivityManager;
        mHasMobileDataFeature = telephonyManager.isDataCapable();
        mDemoModeController = demoModeController;
        mCarrierConfigTracker = carrierConfigTracker;
        mDumpManager = dumpManager;
        mLogBuffer = logBuffer;

        // telephony
        mPhone = telephonyManager;

        // wifi
        mWifiManager = wifiManager;

        mLocale = mContext.getResources().getConfiguration().locale;
        mAccessPoints = accessPointController;
        mDataUsageController = dataUsageController;
        mDataUsageController.setNetworkController(this);
        // TODO: Find a way to move this into DataUsageController.
        mDataUsageController.setCallback(new DataUsageController.Callback() {
            @Override
            public void onMobileDataEnabled(boolean enabled) {
                mCallbackHandler.setMobileDataEnabled(enabled);
                notifyControllersMobileDataChanged();
            }
        });

        mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature,
                mCallbackHandler, this, mWifiManager, trackerFactory,
                mReceiverHandler);

注册广播

@VisibleForTesting
    void registerListeners() {
        for (int i = 0; i < mMobileSignalControllers.size(); i++) {
            MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
            mobileSignalController.registerListener();
        }
        if (mSubscriptionListener == null) {
            mSubscriptionListener = new SubListener(mBgLooper);
        }
        mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
        mTelephonyListenerManager.addActiveDataSubscriptionIdListener(mPhoneStateListener);

        // broadcasts
        IntentFilter filter = new IntentFilter();
        filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
        filter.addAction(Intent.ACTION_SERVICE_STATE);
        filter.addAction(Intent.ACTION_SIM_STATE_CHANGED);
        filter.addAction(Settings.Panel.ACTION_INTERNET_CONNECTIVITY);
        filter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
        filter.addAction(TelephonyManager.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED);
        filter.addAction(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED);
        filter.addAction(TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED);
        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
        mBroadcastDispatcher.registerReceiverWithHandler(this, filter, mReceiverHandler);
        mListening = true;

        // Initial setup of connectivity. Handled as if we had received a sticky broadcast of
        // ConnectivityManager.CONNECTIVITY_ACTION.
        mReceiverHandler.post(this::updateConnectivity);

        // Initial setup of WifiSignalController. Handled as if we had received a sticky broadcast
        // of WifiManager.WIFI_STATE_CHANGED_ACTION or WifiManager.NETWORK_STATE_CHANGED_ACTION
        mReceiverHandler.post(mWifiSignalController::fetchInitialState);

        // Initial setup of mLastServiceState. Only run if there is no service state yet.
        // Each MobileSignalController will also get their corresponding
        mReceiverHandler.post(() -> {
            if (mLastServiceState == null) {
                mLastServiceState = mPhone.getServiceState();
                if (mMobileSignalControllers.size() == 0) {
                    recalculateEmergency();
                }
            }
        });
        updateMobileControllers();

        // Initial setup of emergency information. Handled as if we had received a sticky broadcast
        // of TelephonyManager.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED.
        mReceiverHandler.post(this::recalculateEmergency);
    }

当收到广播时,更新图标

@Override
    public void onReceive(Context context, Intent intent) {
        if (true) {
            Log.d(TAG, "onReceive: intent=" + intent);
        }
        final String action = intent.getAction();
        mLogBuffer.log(
                TAG,
                LogLevel.INFO,
                logMessage -> {
                    logMessage.setStr1(action);
                    return Unit.INSTANCE;
                },
                logMessage -> String.format(
                        Locale.US,
                        "Received broadcast with action \"%s\"",
                        logMessage.getStr1()));
        switch (action) {
            case ConnectivityManager.CONNECTIVITY_ACTION:
                updateConnectivity();
                break;
            case Intent.ACTION_AIRPLANE_MODE_CHANGED:
                refreshLocale();
                updateAirplaneMode(false);
                break;
            case TelephonyManager.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED:
                // We are using different subs now, we might be able to make calls.
                recalculateEmergency();
                break;
            case TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED:
                // Notify every MobileSignalController so they can know whether they are the
                // data sim or not.
                for (int i = 0; i < mMobileSignalControllers.size(); i++) {
                    MobileSignalController controller = mMobileSignalControllers.valueAt(i);
                    controller.handleBroadcast(intent);
                }
                mConfig = Config.readConfig(mContext);
                mReceiverHandler.post(this::handleConfigurationChanged);
                break;

            case TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED: {
                // Notify the relevant MobileSignalController of the change
                int subId = intent.getIntExtra(
                        TelephonyManager.EXTRA_SUBSCRIPTION_ID,
                        INVALID_SUBSCRIPTION_ID
                );
                if (SubscriptionManager.isValidSubscriptionId(subId)) {
                    if (mMobileSignalControllers.indexOfKey(subId) >= 0) {
                        mMobileSignalControllers.get(subId).handleBroadcast(intent);
                    }
                }
            }
            break;
            case Intent.ACTION_SIM_STATE_CHANGED:
                // Avoid rebroadcast because SysUI is direct boot aware.
                if (intent.getBooleanExtra(Intent.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
                    break;
                }
                // Might have different subscriptions now.
                updateMobileControllers();
                break;
            case Intent.ACTION_SERVICE_STATE:
                mLastServiceState = ServiceState.newFromBundle(intent.getExtras());
                if (mMobileSignalControllers.size() == 0) {
                    // If none of the subscriptions are active, we might need to recalculate
                    // emergency state.
                    recalculateEmergency();
                }
                break;
            case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED:
                mConfig = Config.readConfig(mContext);
                mReceiverHandler.post(this::handleConfigurationChanged);
                break;
            case Settings.Panel.ACTION_INTERNET_CONNECTIVITY:
                mMainHandler.post(() -> mInternetDialogFactory.create(true,
                        mAccessPoints.canConfigMobileData(), mAccessPoints.canConfigWifi(),
                        null /* view */));
                break;
            default:
                int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
                        INVALID_SUBSCRIPTION_ID);
                if (SubscriptionManager.isValidSubscriptionId(subId)) {
                    if (mMobileSignalControllers.indexOfKey(subId) >= 0) {
                        mMobileSignalControllers.get(subId).handleBroadcast(intent);
                    } else {
                        // Can't find this subscription...  We must be out of date.
                        updateMobileControllers();
                    }
                } else {
                    // No sub id, must be for the wifi.
                    mWifiSignalController.handleBroadcast(intent);
                }
                break;
        }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1648179.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何应对访问国外服务器缓慢的问题?SDWAN组网是性价比之选

访问国外服务器缓慢通常由以下原因造成&#xff1a; 1、政策限制&#xff1a;我国管理互联网&#xff0c;限制部分国外网站和服务器&#xff0c;以维护国家安全稳定。 2、技术障碍&#xff1a;国内与国际互联网的网络架构和协议存在差异&#xff0c;可能导致数据传输不兼容。 …

F.softmax(cls) + 1e-4

这个代码段中的 softmax 操作结合了一个微小的常数&#xff0c;这个常数通常被称为平滑化参数。softmax 函数将原始的分类输出转换为概率分布&#xff0c;其公式如下&#xff1a; 在实践中&#xff0c;当某些分类得分特别大时&#xff0c;softmax 函数会将对应的概率接近于 1&a…

filezilla 上传文件到服务器

1. 下载windows ftp客户端 https://filezilla-project.org/index.php 点击左侧的 Download FileZilla Client All platforms 默认安装。 2. 双击打开 filezilla 按图中填写&#xff0c;并上传。 主机名: 10.20.89.* 用户名: zhuzh 密码: *** 端口: 22 点击 快速连接&#…

10个必备功能打造跨境电商平台开发全攻略

在跨境电商行业中&#xff0c;拥有一个高效且功能完善的电商平台至关重要。针对跨境电商平台开发&#xff0c;我们将介绍十个必备功能&#xff0c;帮助您全面打造优秀的跨境电商平台。 关键功能一&#xff1a;多语言支持 跨境电商平台开发的首要功能之一是多语言支持。提供多…

探秘Flex布局下子元素宽度超出的那些烦心事

嘿&#xff0c;小伙伴们&#xff01;你们有没有遇到过用Flex布局的时候&#xff0c;子元素的宽度莫名其妙地超出了父元素的情况&#xff1f;别着急&#xff0c;今天我就来给大家揭秘这个问题的来龙去脉&#xff0c;以及一些解决方案。让我们一起来深入探讨&#xff01; 发现问…

73. 矩阵置零/54. 螺旋矩阵

73. 矩阵置零 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]] 思路&#x…

OurBMC开源大赛企业获奖队伍专访来啦!

精彩纷呈的 OurBMC 开源大赛已告一段落&#xff0c;经历为期四个月的实战&#xff0c;各个参赛队伍也积淀了丰富的实践经验与参赛心得。本期&#xff0c;社区特别邀请 OurBMC 开源大赛获奖企业团队分享「走进OurBMC开源大赛&#xff0c;共同践行开放包容、共创共赢的开源精神」…

WordPress建站从入门到精通,跨境电商建站教程

详情介绍 课程内容:WordPress建站从入门到精通,跨境电商建站教程 - 百创网-源码交易平台_网站源码_商城源码_小程序源码 1-WordPress网站的优势 2-如何用Builtwith识别网站的搭建技术? 3-如何配置站长信息? 4-如何使用WordPress虚拟后台 5-如何选择一个好的网站域名?…

【Osek网络管理测试】[TG4_TC5]唤醒条件

&#x1f64b;‍♂️ 【Osek网络管理测试】系列&#x1f481;‍♂️点击跳转 文章目录 1.环境搭建2.测试目的3.测试步骤4.预期结果5.测试结果 1.环境搭建 硬件&#xff1a;VN1630 软件&#xff1a;CANoe 2.测试目的 验证DUT验证DUT睡眠后被唤醒&#xff0c;并再次睡眠能否…

流畅的python-学习笔记_一等函数

函数对象 函数也是对象&#xff0c;操作可像对象一般操作 高阶函数 高阶函数指接受参数为函数&#xff0c;或返回函数的函数 不少高阶函数在py3已经有了替代品。map&#xff0c; filter可通过生成式实现&#xff0c;reduce&#xff08;在functools里&#xff09;可通过sum实…

Web3智能物联网:科技连接的未来世界

在当今科技飞速发展的时代&#xff0c;Web3智能物联网正逐渐成为人们关注的焦点。随着区块链技术的不断成熟和普及&#xff0c;以及物联网的普及和应用&#xff0c;Web3智能物联网作为二者的结合&#xff0c;将为未来的数字世界带来革命性的变化。本文将深入探讨Web3智能物联网…

一文快速掌握高性能内存队列Disruptor

写在文章开头 Disruptor是英国外汇公司LMAX开源的一款高性能内存消息队列&#xff0c;理想情况下单线程可支撑600w的订单。所以本文会从使用以及设计的角度来探讨一下这款神级java消息队列。 Hi&#xff0c;我是 sharkChili &#xff0c;是个不断在硬核技术上作死的 java code…

上市企业扣非净利润是什么意思,可以反映什么问题?

扣非净利润&#xff0c;全称“扣除非经常性损益后的净利润”&#xff0c;是指企业在剔除与正常经营无关的、偶然发生的损益后所得到的利润。这些非经常性损益包括但不限于政府补贴、处置长期资产、税收返还等。 扣非净利润的计算公式为&#xff1a;扣非净利润 净利润 - 非经常…

2-手工sql注入(进阶篇) sqlilabs靶场5-10题

1. 阅读&#xff0c;学习本章前&#xff0c;可以先去看看基础篇&#xff1a;1-手工sql注入(基础篇)-CSDN博客 2. 本章通过对sqlilabs靶场的实战&#xff0c;关于sqlilabs靶场的搭建&#xff1a;Linux搭建靶场-CSDN博客 3. 本章会使用到sqlmap&#xff0c;关于sqlmap的命令&…

TC3xx MTU概述(1)

目录 1.MTU基本功能 2.MBIST 3.小结 1.MTU基本功能 在TC3xx中&#xff0c;MTU(Memory Unit Test)被用来管理控制芯片内部各种RAM的测试、初始化和数据完整性检查。 既然MTU主要是管理和控制&#xff0c;那干活的想必另有他人。所以在该平台中&#xff0c;我们可以看到SRAM…

公众号营业执照已注销,被冻结怎么换成新主体?

公众号迁移有什么作用&#xff1f;只能变更主体吗&#xff1f;长期以来&#xff0c;由于部分公众号在注册时&#xff0c;主体不准确的历史原因&#xff0c;或者公众号主体发生合并、分立或业务调整等现实状况&#xff0c;在公众号登记主体不能对应实际运营人的情况下&#xff0…

第八篇:深入探索操作系统架构:从基础到前沿

深入探索操作系统架构&#xff1a;从基础到前沿 1 引言 在当今这个高速发展的数字时代&#xff0c;操作系统无疑是计算机科学领域的基石之一。它不仅是计算机硬件与最终用户之间的桥梁&#xff0c;更是实现高效计算和资源管理的关键。操作系统的架构&#xff0c;即其内部结构和…

企业节能降耗系统,助力企业节能降耗

随着社会的发展和能源消耗的增加&#xff0c;节能降耗已经成为企业可持续发展的重要课题。为了更有效地监测和管理能源消耗&#xff0c;越来越多的企业开始使用能耗在线监测系统。作为一种节能降耗的有力手段&#xff0c;能耗在线监测系统在企业中得到广泛应用。 能耗在线监测…

AI智能分析视频监控行业的发展趋势和市场发展浅析

监控视频AI智能分析技术的现状呈现出蓬勃发展的态势&#xff0c;这一技术源于计算机视觉和人工智能的研究&#xff0c;旨在将图像与事件描述之间建立映射关系&#xff0c;使计算机能够从视频图像中分辨出目标信息。 在技术上&#xff0c;监控视频AI智能分析技术已经实现了对视…

XAMPP是什么?XAMPP好不好用?

XAMPP是一个免费且开源的软件套件&#xff0c;用于在个人计算机上轻松搭建和运行 Apache 服务器、MySQL 数据库、PHP 和 Perl&#xff0c;让用户可以在个人电脑上搭建服务器环境的平台。 XAMPP的由来是 X(表示跨平台)、Apache、MySQL、PHP 和 Perl 的首字母缩写。 它集成了这…