网络状态监听:监听网络连接类型(WiFi/5G)变化(41)
在鸿蒙(HarmonyOS)开发中,实时监听网络状态是保障应用体验的核心能力。当用户在 Wi-Fi、4G、5G 等网络间切换时,应用需及时响应(如提示网络变化、调整下载并发数),避免因网络波动导致卡顿或流量浪费。
鸿蒙通过 @kit.NetworkKit 中的 @ohos.net.connection 模块提供标准化的网络状态监听接口。以下是完整的实战开发指南:
一、 环境准备与权限配置
网络状态监听属于敏感操作,必须在 module.json5 中声明相关权限:
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
},
{
"name": "ohos.permission.GET_NETWORK_INFO"
}
]
二、 核心代码:网络状态监听与类型识别
通过 createNetConnection 创建网络连接对象,注册各类网络变化事件,并在回调中解析当前网络类型。
import { connection } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct NetworkMonitorDemo {
private netConnection: connection.NetConnection = connection.createNetConnection();
aboutToAppear() {
this.startNetworkMonitor();
}
private startNetworkMonitor() {
// 1. 注册网络订阅(必须先注册,才能接收后续事件)
this.netConnection.register((error: BusinessError) => {
if (error) {
console.error('网络注册监听失败:', JSON.stringify(error));
return;
}
console.info('网络注册监听成功');
});
// 2. 监听网络可用事件
this.netConnection.on('netAvailable', (data: connection.NetHandle) => {
console.info(`网络可用, netId: ${data.netId}`);
});
// 3. 监听网络能力变化(核心:用于识别网络类型切换)
this.netConnection.on('netCapabilitiesChange', (data: connection.NetCapabilityInfo) => {
const bearerTypes = data.netCap?.bearerTypes;
const networkCaps = data.netCap?.networkCap;
// 解析网络类型(Wi-Fi / 蜂窝网络)
if (bearerTypes?.includes(connection.NetBearType.BEARER_WIFI)) {
console.info('当前网络类型: Wi-Fi');
} else if (bearerTypes?.includes(connection.NetBearType.BEARER_CELLULAR)) {
console.info('当前网络类型: 蜂窝网络 (4G/5G)');
}
// 解析网络能力(如是否真正可访问互联网)
if (networkCaps?.includes(connection.NetCap.NET_CAPABILITY_VALIDATED)) {
console.info('网络已验证,可正常访问互联网');
}
});
// 4. 监听网络丢失事件(如断开 Wi-Fi 且无蜂窝网络)
this.netConnection.on('netLost', (data: connection.NetHandle) => {
console.warn(`网络丢失, netId: ${data.netId}`);
});
// 5. 监听网络不可用事件(如连上了 Wi-Fi 但无法上网)
this.netConnection.on('netUnavailable', () => {
console.warn('当前网络不可用');
});
}
aboutToDisappear() {
// 退出页面时取消订阅,防止内存泄漏
this.netConnection.unregister((error: BusinessError) => {
if (error) {
console.error('取消网络监听失败:', JSON.stringify(error));
}
});
}
build() {
Column({ space: 20 }) {
Text('网络状态监听演示')
.fontSize(24)
.fontWeight(FontWeight.Bold)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
三、 进阶:结合状态管理实现 UI 联动
在实际业务中,网络状态通常需要全局共享并驱动 UI 更新。推荐使用 AppStorage 结合 @StorageProp 和 @Watch 实现响应式联动。
// 1. 在工具类或全局监听中,将状态写入 AppStorage
this.netConnection.on('netCapabilitiesChange', (data) => {
let isNetAvailable = data.netCap?.networkCap?.includes(connection.NetCap.NET_CAPABILITY_VALIDATED);
AppStorage.setOrCreate('isNetAvailable', isNetAvailable ?? false);
});
// 2. 在 UI 组件中监听状态变化
@StorageProp('isNetAvailable') @Watch('onNetworkChanged') isNetAvailable: boolean = true;
onNetworkChanged() {
if (this.isNetAvailable) {
console.info('网络已恢复,执行重新连接/恢复下载逻辑');
} else {
console.warn('网络已断开,暂停下载并提示用户');
}
}
开发建议与注意事项
- 区分
netLost与netUnavailable:netLost:网络严重中断或正常断开(如手动关闭 Wi-Fi)。netUnavailable:网络已连接但不可用(如连上了 Wi-Fi 但路由器未连外网,图标显示感叹号)。
- 网络切换的事件触发顺序:当设备从 Wi-Fi 切换到蜂窝网络时,系统会先触发
netLost(Wi-Fi 丢失),再触发netAvailable(蜂窝网络可用)。在开发重连逻辑时需注意时序。 - 低功耗设计:鸿蒙网络监听采用事件订阅机制,仅在状态变化时唤醒应用回调,避免了持续轮询带来的高耗电问题。
- 不支持主动切换:系统原生能力仅支持通过回调“感知”网络切换,不支持应用主动进行网络切换。
四、 精准识别蜂窝网络代际(5G/4G/3G/2G)
基础的 connection 模块只能区分出当前是否处于“蜂窝网络”状态。如果需要精准识别当前是 5G、4G 还是 3G,需要结合 @ohos.telephony.radio 模块获取信号信息。
核心代码示例:
import { connection } from '@kit.NetworkKit';
import { radio } from '@kit.TelephonyKit';
// 当监听到当前网络为蜂窝网络时,进一步获取具体代际
async function getCellularGeneration() {
try {
// 获取当前设备的信号信息列表(支持双卡)
const signalInfos = await radio.getSignalInformation();
if (signalInfos && signalInfos.length > 0) {
// 获取主卡的信号类型
const signalType = signalInfos[0].signalType;
switch (signalType) {
case radio.NetworkType.NETWORK_TYPE_NR:
console.info('当前蜂窝网络: 5G');
break;
case radio.NetworkType.NETWORK_TYPE_LTE:
console.info('当前蜂窝网络: 4G');
break;
case radio.NetworkType.NETWORK_TYPE_WCDMA:
case radio.NetworkType.NETWORK_TYPE_TDSCDMA:
console.info('当前蜂窝网络: 3G');
break;
default:
console.info('当前蜂窝网络: 2G/未知');
break;
}
}
} catch (err) {
console.error('获取蜂窝网络代际失败');
}
}
五、 弱网状态感知(ASCF 框架)
在音视频通话、实时游戏等对网络延迟敏感的场景中,仅知道“网络是否连接”是不够的,还需要感知当前是否处于“弱网”状态。鸿蒙 ASCF 框架提供了专门的弱网监听接口。
核心代码示例:
import { has } from '@kit.ASCFKit'; // 假设基于 ASCF 框架
// 监听弱网状态变化
has.onNetworkWeakChange((res) => {
console.info(`弱网状态变更: ${res.weakNet}, 当前网络类型: ${res.networkType}`);
if (res.weakNet) {
// 弱网策略:降低视频码率、减少心跳频率、暂停后台预加载等
console.warn('检测到弱网,正在切换至低画质模式...');
} else {
// 网络恢复:恢复正常策略
console.info('网络状况良好,恢复标准画质');
}
});
// 在生命周期中取消监听
has.offNetworkWeakChange();
六、 多网并发与连接迁移(Network Boost Kit)
对于大型文件下载、直播推流等高吞吐业务,鸿蒙提供了 Network Boost Kit,允许应用感知多网并发状态(例如同时使用 Wi-Fi 和蜂窝网络),从而制定更优的数据传输策略。
核心代码示例:
import { netHandover } from '@kit.NetworkBoostKit';
import { BusinessError } from '@kit.BasicServicesKit';
// 订阅多网状态信息变化
try {
netHandover.on('multiPathStateChange', (data: netHandover.MultiPathStateInfo) => {
console.info("多网状态变化: " + JSON.stringify(data));
// 根据多网状态调整并发下载线程数或传输策略
});
} catch (err) {
console.error('监听多网状态失败: ' + (err as BusinessError).message);
}
// 业务结束时取消订阅
try {
netHandover.off('multiPathStateChange');
} catch (err) {
console.error('取消多网状态监听失败: ' + (err as BusinessError).message);
}
七、 网络质量量化监控(延迟、带宽、信号强度)
在音视频通话、实时游戏等对网络延迟极度敏感的场景中,除了感知“弱网”,还需要获取具体的网络质量指标(如 RTT 延迟、上下行带宽、信号强度 RSRP)。由于系统可能没有直接提供实时的质量变化监听,通常采用定时主动探测的方式来实现。
核心代码示例:
import { connection } from '@kit.NetConnectionKit';
// 定义网络质量模型
interface NetworkQuality {
level: 'EXCELLENT' | 'GOOD' | 'FAIR' | 'POOR' | 'UNKNOWN';
signalStrength: number;
latency: number;
bandwidth: number;
}
// 定时检测网络质量
async function measureNetworkQuality(): Promise<NetworkQuality> {
const startTime = Date.now();
try {
// 通过发起轻量级请求来测量延迟(RTT)
await fetch('https://connectivitycheck.gstatic.com/generate_204', { timeout: 5000 });
const latency = Date.now() - startTime;
// 根据延迟评估质量等级
let level: NetworkQuality['level'] = 'UNKNOWN';
if (latency < 100) level = 'EXCELLENT';
else if (latency < 300) level = 'GOOD';
else if (latency < 800) level = 'FAIR';
else level = 'POOR';
return { level, signalStrength: 0, latency, bandwidth: 0 };
} catch (err) {
return { level: 'POOR', signalStrength: 0, latency: -1, bandwidth: 0 };
}
}
// 每 5 秒执行一次质量评估
setInterval(async () => {
const quality = await measureNetworkQuality();
console.info(`当前网络质量: ${quality.level}, 延迟: ${quality.latency}ms`);
}, 5000);
八、 智能 DNS 解析
在多网络并存或复杂网络环境下,直接使用域名发起请求可能会遇到 DNS 劫持或解析缓慢的问题。鸿蒙提供了系统级的智能 DNS 解析接口,可以直接获取目标域名的 IP 地址列表,便于应用层自行管理连接。
核心代码示例:
import { connection } from '@kit.NetworkKit';
async function resolveDomain() {
try {
const addresses = await connection.getAddressesByName("www.example.com");
console.info("解析到的 IP 地址列表:", addresses.join(', '));
// 业务层可使用解析出的 IP 直接建立连接,绕过系统默认 DNS
} catch (err) {
console.error("DNS 解析失败:", (err as BusinessError).message);
}
}
九、 底层网络状态强制修正
在某些极端场景下(如底层网卡驱动异常、代理软件干扰),应用内部记录的网络状态可能与系统网络管理器不一致。鸿蒙提供了强制报告网络状态的接口,用于纠正系统的误判。
核心代码示例:
import { connection } from '@kit.NetworkKit';
// 当发现网络状态异常且确认当前网络不可用时,强制向系统报告网络断开
function forceReportDisconnect(badNetHandle: connection.NetHandle) {
connection.reportNetDisconnected(badNetHandle);
console.warn('已强制报告网络断开');
}
// 当确认某个网络句柄实际可用,但系统未识别时,强制报告连接
function forceReportConnect(goodNetHandle: connection.NetHandle) {
connection.reportNetConnected(goodNetHandle);
console.info('已强制报告网络连接');
}
底层通信资源管控与避坑
在复杂的网络切换过程中,底层通信资源的管理至关重要,处理不当极易导致内存泄漏或请求异常。
- Socket 资源强制释放:当监听到网络切换(如 Wi-Fi 切 5G)或网络丢失时,必须主动关闭旧的 Socket 连接。旧的网络句柄在新的网络环境下已失效,继续持有会导致资源泄漏。
- 推荐使用高级通信套件:在多网络频繁切换的场景下,强烈建议使用
@kit.RemoteCommunicationKit替代原生的 HTTP 模块,它内置了更好的连接池管理和网络异常恢复机制。 - 紧急情况下的状态修正:当遇到应用内部记录的网络状态与系统管理器不一致时(例如应用认为已断网,但系统实际可用),可以调用
connection.reportNetDisconnected(badNetHandle)或connection.reportNetConnected(goodNetHandle)强制向系统报告网络状态。 - 生命周期严格绑定:网络监听会持续占用系统资源。务必在
EntryAbility的onCreate中开启订阅,在onWindowStageDestroy中关闭订阅,防止应用进入后台后仍进行不必要的状态回调。
更多推荐


所有评论(0)