当前位置: 首页 > news >正文

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

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

    @VisibleForTestingNetworkControllerImpl(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;// telephonymPhone = telephonyManager;// wifimWifiManager = 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() {@Overridepublic void onMobileDataEnabled(boolean enabled) {mCallbackHandler.setMobileDataEnabled(enabled);notifyControllersMobileDataChanged();}});mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature,mCallbackHandler, this, mWifiManager, trackerFactory,mReceiverHandler);

注册广播

@VisibleForTestingvoid 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);// broadcastsIntentFilter 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_ACTIONmReceiverHandler.post(mWifiSignalController::fetchInitialState);// Initial setup of mLastServiceState. Only run if there is no service state yet.// Each MobileSignalController will also get their correspondingmReceiverHandler.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);}

当收到广播时,更新图标

@Overridepublic 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 changeint 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;}}

相关文章:

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

1. 状态栏信号图标 1.1 WIFI信号显示 WIFI信号在状态栏的显示如下图所示 当WiFi状态为关闭时&#xff0c;状态栏不会有任何显示。当WiFi状态打开时&#xff0c;会如上图所示&#xff0c;左侧表示有可用WiFi&#xff0c;右侧表示当前WiFi打开但未连接。 当WiFi状态连接时&#x…...

更改 DeepXDE 的后端

DeepXDE 库为科学计算和工程优化等领域提供了深度学习方法&#xff0c;是一个非常有用的工具。其中一个重要的功能是它允许用户自定义后端。在本文中&#xff0c;我们将指导如何更改 DeepXDE 的后端&#xff0c;并且验证更改是否成功。 更改 DeepXDE 的后端 DeepXDE 支持多种…...

SpringBoot之Zuul服务

概述 Spring Cloud Netflix zuul组件是微服务架构中的网关组件,Zuul作为统一网关,是所有访问该平台的请求入口,核心功能是路由和过滤。 目前公司业务就是基于Zuul搭建的网关服务,且提供的服务包括转发请求(路由)、黑名单IP访问拦截、URL资源访问时的权限拦截、统一访问日志记…...

Go-变量

可以理解为一个昵称 以后这个昵称就代指这些信息 var sg string "czy" 声明赋值 package mainimport "fmt"func main() {var sg string "陈政洋"fmt.Println(sg)var age int 73fmt.Println(age)var flag bool truefmt.Println(flag) } …...

【CTF-Crypto】RSA-选择明密文攻击 一文通

RSA&#xff1a;选择明密文攻击 关于选择明/密文攻击&#xff0c;其实这一般是打一套组合拳的&#xff0c;在网上找到了利用的思路&#xff0c;感觉下面这个题目是真正将这个问题实现了&#xff0c;所以还是非常棒的一道题&#xff0c;下面先了解一下该知识点&#xff1a;(来自…...

Pytorch基础:torch.expand() 和 torch.repeat()

在torch中&#xff0c;如果要改变某一个tensor的维度&#xff0c;可以利用view、expand、repeat、transpose和permute等方法&#xff0c;这里对这些方法的一些容易混淆的地方做个总结。 expand和repeat函数是pytorch中常用于进行张量数据复制和维度扩展的函数&#xff0c;但其…...

如何正确安装Scrapy 2.6.1并解决常见的Python环境问题

在配置Python环境和安装包时&#xff0c;常常会遇到版本冲突和路径问题&#xff0c;特别是当系统中存在多个Python版本时。本文将指导你如何在CentOS系统中正确使用pip3安装Scrapy 2.6.1&#xff0c;并解决一些常见的环境问题。 步骤1: 确认和升级 pip3 确认 pip3 的版本&…...

阵痛中的乳业产业,何时才能成为下一个啤酒产业?

说起饮品&#xff0c;近年来中国啤酒业中各大品牌齐齐聚焦高端化的趋势绝对值得一提。然而&#xff0c;与之相反&#xff0c;国内乳业却是仍未进入高端化阶段&#xff0c;甚至陷入了周期底部中。 图源&#xff1a;中国圣牧财报 增收降利 牧企承受巨大的供需缺口压力 从产业链…...

关于模型参数融合的思考

模型参数融合通常指的是在训练过程中或训练完成后将不同模型的参数以某种方式结合起来&#xff0c;以期望得到更好的性能。这种融合可以在不同的层面上进行&#xff0c;例如在神经网络的不同层之间&#xff0c;或者是在完全不同的模型之间。模型参数融合的目的是结合不同模型的…...

Windows MySQL本地服务器设置并导入数据库和数据

文章目录 小结问题及解决导出数据库Windows MySQL本地服务器设置导入数据库和数据 参考 小结 最近需要在本地Windows环境中设置MySQL服务器&#xff0c;并导入数据库和数据&#xff0c;记录过程。 问题及解决 导出数据库 首先需要导出数据库&#xff1a; C:\mysql-8.0.37-…...

豪投巨资,澳大利亚在追逐海市蜃楼吗?

澳大利亚政府正在积极投资于量子计算领域。继2021年向量子技术投资逾1亿澳元后&#xff0c;2023年5月&#xff0c;该国发布了首个国家量子战略&#xff0c;详细阐述了如何把握量子技术的未来及保持全球领先地位。 澳大利亚的国家量子战略概述 原文链接&#xff1a; https://ww…...

面试集中营—Redis架构篇

一、Redis到底是多线程还是单线程 1、redis6.0版本之前的单线程&#xff0c;是指网络请求I/O与数据的读写是由一个线程完成的&#xff1b; 2、redis6.0版本升级成了多线程&#xff0c;指的是在网络请求I/O阶段应用的多线程技术&#xff1b;而键值对的读写还是由单线程完成的。所…...

05_kafka-整合springboot

文章目录 kafka 整合 springboot pom.xml <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.5.RELEASE</version> </parent> <dependencies>&…...

论UML在学情精准测评系统中的应用

摘要简介 项目背景&#xff1a; 随着教育改革的不断深入&#xff0c;对学生学情的精准测评成为教育教学工作中的重要环节。为了解决传统学情测评方式主观性强、效率低、反馈不及时等问题&#xff0c;我们团队受教育主管部门委托&#xff0c;承担了中小学学情精准测评系统&…...

Day23 代码随想录打卡|字符串篇---重复的子字符串

题目&#xff08;leecode T459&#xff09;&#xff1a; 给定一个非空的字符串 s &#xff0c;检查是否可以通过由它的一个子串重复多次构成。给定的字符串只含有小写英文字母&#xff0c;并且长度不超过10000。fang 移动匹配。分析可以由自己的子串构成的字符串&#xff0c;肯…...

【win10 文件夹数量和看到不一致查看隐藏文件已经打开,Thumb文件作妖】

目录 任务介绍&#xff1a;重命名规则修改前修改后 实现思路VB代码实现BUG犯罪现场&#xff08;眼见不一定为实&#xff09;破案1&#xff1a;抓顶风作案的反贼&#xff01;&#xff01;&#xff01;破案2&#xff1a;破隐身抓刺客&#xff01;&#xff01;&#xff01;杀器&am…...

ctfshow web入门 sql注入 web224--web233

web224 扫描后台&#xff0c;发现robots.txt&#xff0c;访问发现/pwdreset.php &#xff0c;再访问可以重置密码 &#xff0c;登录之后发现上传文件 检查发现没有限制诶 上传txt,png,zip发现文件错误了 后面知道群里有个文件能上传 <? _$GET[1]_?>就是0x3c3f3d60245…...

「Java开发指南」如何用MyEclipse搭建GWT 2.1和Spring?(一)

本教程将指导您如何生成一个可运行的Google Web Toolkit (GWT) 2.1和Spring应用程序&#xff0c;该应用程序为域模型实现了CRUD应用程序模式。在本教程中&#xff0c;您将学习如何&#xff1a; 安装Google Eclipse插件为GWT配置一个项目搭建从数据库表到一个现有的项目GWT编译…...

python同时进行字符串的多种替换

一些常见的方法&#xff1a; 使用str.replace()方法&#xff1a;这是一种简单的方法&#xff0c;但是如果你有多个替换需要进行&#xff0c;可能会变得很繁琐。 text "This is a sample text with some words." text text.replace("sample", "exa…...

【Java基础题型】用筛法求之N内的素数(老题型)

输入格式 N输出格式 0&#xff5e;N的素数样例输入 100样例输出 2 3 5 7 11 13 17 19 23 29 31 37 老朋友素数了属于是&#xff01; 方法1&#xff1a;(穷举法) 通过遍历 i 的所有除数&#xff0c;如果除以除数后商变成了0&#xff0c;那么把布尔值变成假的。表示不是素数 【…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

JDK 17 新特性

#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持&#xff0c;不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的&#xff…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...