19、网络连接管理:ConnectivityService、WifiService、移动数据与VPN
网络连接管理,说白了就是Android系统里那个看不见的“交通调度中心”。你手机上的微信、抖音、浏览器,它们怎么知道该走Wi-Fi还是走移动数据?VPN开启后流量怎么被“劫持”的?这些背后都是几个核心服务在协作。
我个人习惯把这一块比作“网络路由的神经中枢”。今天我们就深入扒一扒ConnectivityService、WifiService、移动数据管理以及VPN的底层逻辑。
19.1 ConnectivityService:网络世界的“总调度”
ConnectivityService是Android网络框架里最核心的服务。它不直接管硬件,但它知道当前有哪些网络可用,哪个网络优先级最高,以及怎么把网络切换通知给上层应用。
我记得有一次排查一个“Wi-Fi已连接但无法上网”的bug,最后发现是ConnectivityService的评分机制出了问题。它给一个信号弱但能上网的Wi-Fi打了低分,结果系统一直用移动数据,用户就以为Wi-Fi坏了。
19.1.1 网络评分与选网逻辑
ConnectivityService内部维护着一个网络评分机制。每个网络(Wi-Fi、移动数据、以太网等)都有一个NetworkAgent,它会向ConnectivityService上报当前网络的质量指标:
- 信号强度:RSSI值,Wi-Fi和蜂窝都有
- 链路质量:丢包率、延迟、带宽
- 验证结果:是否能访问Google服务器(国内是其他验证点)
评分规则大致如下:
| 网络类型 | 默认基础分 | 加分项 | 减分项 |
|---|---|---|---|
| Wi-Fi | 60 | 信号强+10,已验证+20 | 信号弱-10,无互联网-40 |
| 移动数据 | 50 | 已验证+20 | 信号弱-15,漫游-20 |
| 以太网 | 70 | 已验证+20 | 无 |
ConnectivityService会选评分最高的网络作为“默认网络”。所有不指定网络的socket,都会走这个默认网络。
核心逻辑:ConnectivityService通过NetworkRanker对所有可用网络排序,得分最高的成为defaultNetwork。应用层通过NetworkCallback监听网络变化。
19.1.2 网络切换流程
当Wi-Fi信号变弱,或者移动数据信号恢复时,ConnectivityService会触发网络切换。流程大致是:
- NetworkMonitor检测到当前网络不可用(比如ping不通验证服务器)
- ConnectivityService收到LOST事件,标记该网络为“验证失败”
- 重新计算所有网络评分,选出新的最优网络
- 发送NETWORK_CHANGED广播,通知所有注册的应用
- 更新默认路由表,把默认网关指向新网络
嗯,这里要注意:网络切换不是瞬间完成的。Android 12之后引入了“瞬时切换”机制,能在100ms内完成路由切换,但前提是目标网络已经提前建立好连接。
19.2 WifiService:Wi-Fi连接的“管家”
WifiService是专门管理Wi-Fi模块的服务。它运行在system_server进程里,通过WifiNative与底层wpa_supplicant或wificond通信。
我曾经遇到过一个诡异的问题:手机连上Wi-Fi后,每隔几分钟就断连一次。抓了tcpdump发现是DHCP续租失败。最后定位到是WifiService里的IpManager在续租时没处理好超时重试。
19.2.1 WifiService的架构分层
WifiService的架构可以分成三层:
- 应用层:WifiManager,提供API给App调用(如scan、connect、disconnect)
- 服务层:WifiServiceImpl,处理权限校验、状态机管理
- 底层:WifiNative,通过HIDL或AIDL与wpa_supplicant通信
核心状态机是WifiStateMachine,它管理着Wi-Fi从关闭到扫描、连接、断开、漫游等所有状态。
个人经验:调试Wi-Fi问题时,最常用的命令是adb shell dumpsys wifi。它能输出当前连接状态、信号强度、DHCP信息、甚至上次断连的原因。我几乎每次排查Wi-Fi问题都会先跑这个命令。
19.2.2 扫描与连接流程
Wi-Fi扫描分为主动扫描和被动扫描。主动扫描会发送Probe Request帧,被动扫描则监听Beacon帧。WifiService默认每30秒做一次后台扫描,但Android 9之后引入了“扫描节流”机制,防止频繁扫描耗电。
连接流程大致是:
- App调用WifiManager.connect()
- WifiService解析SSID和密码,构造WifiConfiguration
- 通过WifiNative下发连接命令到wpa_supplicant
- wpa_supplicant完成4次握手,建立连接
- WifiService收到连接成功回调,启动DHCP获取IP
- DHCP成功后,通知ConnectivityService该网络可用
避坑指南:我曾经遇到过一个问题——某些路由器在5GHz频段下,wpa_supplicant的4次握手总是超时。后来发现是路由器开启了802.11r快速漫游,但手机端的wpa_supplicant配置没同步。解决方案是在wpa_supplicant.conf里加上disable_11r=1。
19.3 移动数据管理:蜂窝网络的“守门员”
移动数据管理主要由TelephonyNetworkService和DataConnection负责。它不像Wi-Fi那样有独立的Service进程,而是集成在Telephony框架里。
移动数据的核心是APN(接入点名称)。每个运营商都有自己的一套APN配置,包括APN类型(default、supl、ims、mms等)。
19.3.1 数据连接的建立与释放
当应用发起网络请求时,如果当前没有可用的移动数据连接,ConnectivityService会请求TelephonyNetworkService建立数据连接。流程如下:
- TelephonyNetworkService收到请求,检查当前SIM卡的APN配置
- 通过RIL(Radio Interface Layer)发送SETUP_DATA_CALL命令到基带
- 基带与运营商网络建立PDP上下文,分配IP地址
- 返回DataCallResponse,包含IP、网关、DNS等信息
- TelephonyNetworkService创建NetworkAgent,上报给ConnectivityService
释放连接时,如果所有使用该网络的socket都关闭了,且没有其他应用依赖,ConnectivityService会通知TelephonyNetworkService去释放数据连接。
关键点:移动数据连接是“按需建立”的。系统不会一直保持数据连接,而是根据应用的实际请求来创建和销毁。这就是为什么你关掉所有后台应用后,移动数据图标会消失——实际上数据连接已经被释放了。
19.4 VPN:网络流量的“隧道”
VPN的实现原理,说白了就是在网络协议栈里插入一个虚拟网络接口。所有从应用发出的数据包,都会被路由到这个虚拟接口,然后经过加密后发送到真正的物理网络。
Android的VPN框架分为三层:
- 应用层:VpnService,App通过它创建VPN连接
- 框架层:ConnectivityService管理VPN网络的状态
- 内核层:TUN/TAP驱动,创建虚拟网络接口
19.4.1 VPN的建立流程
当用户开启VPN时,流程是这样的:
- App(如OpenVPN)调用VpnService.Builder建立VPN
- 系统创建一个TUN虚拟接口,分配一个虚拟IP地址
- App通过JNI调用内核接口,配置路由规则
- 所有匹配路由的数据包,都会被送到TUN接口
- App从TUN接口读取原始数据包,加密后通过物理网络发送
这里有个关键点:VPN的路由规则可以控制哪些流量走VPN,哪些流量直连。比如你可以配置只有访问公司内网的流量走VPN,其他流量正常走Wi-Fi。
我建议:在开发VPN应用时,一定要处理好“分应用路由”。Android 5.0之后支持按应用设置VPN路由,这样可以让某些应用绕过VPN(比如银行App)。实现方式是在VpnService.Builder里调用addAllowedApplication()或addDisallowedApplication()。
19.4.2 VPN与ConnectivityService的交互
VPN网络在ConnectivityService里也是一个普通的NetworkAgent。它有自己的评分,但通常VPN网络的评分会被设置为最高,以确保所有流量都走VPN。
但这里有个坑:如果VPN连接断开,ConnectivityService需要快速切换到原始网络。我曾经遇到过一个场景——VPN断开后,系统没有及时切换路由,导致应用一直尝试连接VPN的虚拟IP,结果全部超时。
避坑指南:VPN应用在断开时,一定要调用VpnService.Builder的revoke()方法,通知系统清理路由规则。否则系统可能残留VPN的路由表项,导致网络不通。我见过好几个第三方VPN应用都踩过这个坑。
19.5 网络连接管理的整体架构
为了让你更直观地理解这些服务之间的关系,我画了一张架构图:
从这张图你可以看到,整个网络连接管理是分层协作的。应用层通过Manager API发起请求,框架层的三个核心服务负责调度和状态管理,内核层提供实际的网络接口,硬件层完成物理通信。
我个人觉得,理解这些服务之间的协作关系,比死记硬背API更重要。你想想看,当你在手机上打开一个网页时,背后是ConnectivityService在决定走哪条路,WifiService或TelephonyNetworkService在维护连接,VPN服务可能在中间做加密转发——这一整套流程,任何一个环节出问题,都会导致网络不通。
总结:网络连接管理的核心是ConnectivityService的评分选网机制,WifiService和TelephonyNetworkService作为网络提供者,VPN作为流量隧道。调试时重点关注dumpsys输出和路由表变化。
公众号:蓝海资料掘金营,微信deep3321