系列目录 :第一篇:全景图与调用链路概览 | 第二篇:内核层---netfilter/iptables与路由策略 | 第三篇:Native层(上)---netd守护进程与CommandListener | 第四篇:Native层(下)---netd Controller详解 | 第五篇:Framework层(上)---ConnectivityService核心机制 | 第六篇:Framework层(下)---NMS/NPMS/NSS三大服务 | 第七篇:连接建立---WiFi/移动数据/以太网完整流程 | 第八篇:应用API层---ConnectivityManager使用与实战调试
一、ConnectivityManager 核心 API
源码路径 : frameworks/base/core/java/android/net/ConnectivityManager.java
1.1 查询网络状态(旧 API)
java
ConnectivityManager cm = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo wifiInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
NetworkInfo mobileInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null && activeNetwork.isConnected();
关键 :旧 API 通过
TYPE_WIFI、TYPE_MOBILE等常量按网络类型查询,getActiveNetworkInfo()返回当前默认网络信息,Android 5.0 后推荐使用NetworkRequest替代。
1.2 请求特定网络(新 API --- Android 5.0+)
java
NetworkRequest request = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
ConnectivityManager.NetworkCallback callback = new ConnectivityManager.NetworkCallback() {
@Override public void onAvailable(Network network) { /* 网络可用 */ }
@Override public void onLost(Network network) { /* 网络丢失 */ }
@Override public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) {}
@Override public void onLinkPropertiesChanged(Network network, LinkProperties lp) {}
};
cm.requestNetwork(request, callback);
// 释放时:cm.unregisterNetworkCallback(callback);
关键设计 :
NetworkRequest.Builder通过addTransportType和addCapability精确指定网络需求,NetworkCallback以回调方式通知网络状态变化,替代了传统广播机制。
1.3 绑定进程/套接字到特定网络
java
// 绑定整个进程
Network wifiNetwork = ...;
cm.bindProcessToNetwork(wifiNetwork);
// 只绑定单个 socket
Network mobileNetwork = ...;
Socket socket = new Socket();
mobileNetwork.bindSocket(socket);
// 打开指定网络的 URL 连接
URL url = new URL("https://example.com");
HttpURLConnection conn = (HttpURLConnection) wifiNetwork.openConnection(url);
关键设计 :
bindProcessToNetwork绑定整个进程的网络出口,bindSocket仅绑定单个 Socket,openConnection在指定Network上打开 URL 连接,三者提供不同粒度的网络绑定能力。
1.4 多网络并存的实战示例
java
// 下载大文件用 WiFi,IM 长连接用最优网络
NetworkRequest downloadReq = new NetworkRequest.Builder()
.addTransportType(TRANSPORT_WIFI)
.addCapability(NET_CAPABILITY_INTERNET)
.addCapability(NET_CAPABILITY_NOT_METERED)
.build();
cm.requestNetwork(downloadReq, new NetworkCallback() {
@Override public void onAvailable(Network network) {
network.bindSocket(downloadSocket);
startDownload();
}
});
NetworkRequest imReq = new NetworkRequest.Builder()
.addCapability(NET_CAPABILITY_INTERNET)
.build();
cm.requestNetwork(imReq, new NetworkCallback() {
@Override public void onAvailable(Network network) {
cm.bindProcessToNetwork(network);
startIMConnection();
}
});
关键设计 :同时注册两个
NetworkRequest,通过不同的NetworkCallback将下载流量绑定到 WiFi(NOT_METERED),将 IM 长连接绑定到最优网络(仅要求INTERNET),实现多网络并发使用。
二、调试命令大全
2.1 dumpsys --- 网络诊断的最强工具
源码路径 :adb shell(Android 调试桥)
bash
adb shell dumpsys connectivity # ConnectivityService 完整状态
adb shell dumpsys netpolicy # 网络策略与省电模式
adb shell dumpsys netstats # 流量统计(按 UID+接口)
adb shell dumpsys wifi # WiFi 完整状态
关键 :
dumpsys是网络诊断的首选工具,dumpsys connectivity输出包含所有 NetworkAgent、NetworkRequest、评分和验证状态。
2.2 ndc --- 直接与 netd 通信
源码路径 :adb shell(Android 调试桥)
bash
adb shell ndc interface list # 列出所有接口
adb shell ndc firewall is_enabled # 防火墙状态
adb shell ndc bandwidth getiquota rmnet_data0 # 查看配额
adb shell ndc tether status # 网络共享状态
adb shell ndc resolver getdnsserversnetid 100 # DNS 配置
adb shell ndc network route add 100 wlan0 0.0.0.0/0 192.168.1.1
关键 :
ndc通过NativeDaemonConnector与netd守护进程直接通信,可执行CommandListener中注册的所有命令。
2.3 iptables / iproute2 --- 内核层诊断
源码路径 :adb shell(Android 调试桥)
bash
adb shell iptables -L -n -v # filter 表规则
adb shell iptables -t nat -L -n -v # nat 表(网络共享)
adb shell iptables -L fw_powersave -n -v # 省电模式规则
adb shell iptables -L fw_dozable -n -v # Doze 规则
adb shell ip rule show # 策略路由规则
adb shell ip route show table 100 # netId=100 的路由表
adb shell ip addr show # 所有接口地址
关键 :
iptables和ip命令直接查看内核层网络规则,是排查防火墙拦截和路由异常的核心手段。
2.4 tcpdump --- 抓包分析
源码路径 :adb shell(Android 调试桥)
bash
adb shell tcpdump -i wlan0 -w /sdcard/cap.pcap # 抓 WiFi 包
adb shell tcpdump -i wlan0 port 53 # 只抓 DNS
adb pull /sdcard/cap.pcap .
关键 :
tcpdump抓取原始网络数据包,配合 Wireshark 分析协议交互细节,是定位网络不通问题的终极手段。
2.5 日志分析技巧
源码路径 :adb shell(Android 调试桥)
bash
# WiFi 连接过程
adb logcat -s WifiStateMachine:D WifiNative:D DhcpClient:D
# ConnectivityService 评分切换
adb logcat -s ConnectivityService:D
# netd 命令交互
adb logcat -s NativeDaemonConnector:D
# 网络策略
adb logcat -s NetworkPolicy:D
# 移动数据连接
adb logcat -s DcTracker:D DataConnection:D RILJ:D
# 全套网络日志
adb logcat -s ConnectivityService:D NetworkPolicy:D NetworkStats:D NetworkMonitor:D
关键 :
logcat -s按 tag 过滤日志,覆盖 WiFi 连接、评分切换、netd 交互、网络策略和移动数据连接五大核心模块。
三、六大典型问题分析
问题一:"WiFi 已连接但无法上网"
排查 :检查 DHCP 是否获取 IP (ip addr show wlan0),检查默认路由 (ip route show table 100),检查 DNS 可达性 (ping 8.8.8.8),检查 NetworkMonitor 验证 (dumpsys connectivity | grep VALIDATED),检查 Captive Portal (dumpsys connectivity | grep captive)。
常见原因:DHCP 失败、NetworkMonitor 验证失败(Captive Portal 检测不可达)、DNS 错误、iptables 防火墙阻止。
问题二:"WiFi 切换移动数据太慢"
排查 :dumpsys connectivity 查看评分切换,logcat -s WifiStateMachine 查看断开时间点。常见原因:Linger 暂缓时间过长、DHCP 租约过短、移动数据未保持激活、依赖 CONNECTIVITY_ACTION 广播延迟。
优化:保持移动数据 always on、使用 NetworkCallback 替代 BroadcastReceiver、调整 WiFi 信号阈值。
问题三:"省电模式限制了后台网络"
排查 :iptables -L fw_powersave -n -v | grep <uid> 查看是否被拦截,dumpsys netpolicy 查看白名单。解决:加入省电白名单、使用前台服务保持连接。
问题四:"VPN 连上后网络断开"
排查 :dumpsys connectivity | grep VPN 查看 VPN NetworkAgent,ip rule show 查看 fwmark 规则,ndc resolver getdnsserversnetid <vpnNetId> 检查 DNS。常见原因:路由表错误、VPN DNS 不可达、路由表未正确清理。
问题五:"热点共享失败"
排查 :cat /proc/sys/net/ipv4/ip_forward(应为 1),iptables -t nat -L POSTROUTING(应有 MASQUERADE),ps | grep dnsmasq(应正在运行)。
问题六:"流量统计不准确"
排查 :dumpsys netstats 查看系统统计,cat /proc/net/xt_qtaguid/stats 查看内核原始数据。常见原因:IP 层 vs 链路层统计差异、运营商包含信令流量、计费周期不一致。
四、快速诊断速查表
| 症状 | 第一命令 | 关键检查点 |
|---|---|---|
| WiFi 无法上网 | `dumpsys connectivity | grep -A10 WiFi` |
| 切换慢 | logcat -s ConnectivityService |
Linger 时间、评分变化 |
| 应用被限网 | `iptables -L fw_powersave -n | grep |
| VPN 故障 | ip rule show |
fwmark 优先级、tun0 接口 |
| 热点失败 | cat /proc/sys/net/ipv4/ip_forward |
IP 转发、NAT 规则 |
| 流量异常 | dumpsys netstats |
按 UID 定位、与 /proc 对比 |
五、系列总结
本系列从 Linux 内核一路走到 Android 应用 API,覆盖了以下关键层级:
| 层级 | 核心内容 | 关键文件/模块 |
|---|---|---|
| 内核层 | netfilter/iptables、fwmark、策略路由 | RouteController.cpp |
| Native 层 | netd 守护进程、八大 Controller | main.cpp / CommandListener.cpp |
| Framework 层 | ConnectivityService + NMS/NPMS/NSS | ConnectivityService.java |
| 网络代理层 | WiFi/移动数据/以太网 NetworkAgent | WifiStateMachine / DataConnection |
| 应用 API 层 | ConnectivityManager + 调试工具链 | ConnectivityManager.java |
理解 Android 网络系统的最有效方式:带着一个问题,沿着调用链路从头走到尾。每次追踪一个具体场景(如 WiFi 连接),从应用层一直追到内核 iptables 规则,这种"纵深阅读"能让各个环节的交互变得清晰。
下一篇将进入车机定制实践,展示多接口绑定、流量配额管理和网络共享管控的完整实现方案,将前八篇的理论知识应用到实际工程场景中。