在鸿蒙(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('网络已断开,暂停下载并提示用户');
  }
}

开发建议与注意事项

  1. 区分 netLost 与 netUnavailable
    • netLost:网络严重中断或正常断开(如手动关闭 Wi-Fi)。
    • netUnavailable:网络已连接但不可用(如连上了 Wi-Fi 但路由器未连外网,图标显示感叹号)。
  2. 网络切换的事件触发顺序:当设备从 Wi-Fi 切换到蜂窝网络时,系统会先触发 netLost(Wi-Fi 丢失),再触发 netAvailable(蜂窝网络可用)。在开发重连逻辑时需注意时序。
  3. 低功耗设计:鸿蒙网络监听采用事件订阅机制,仅在状态变化时唤醒应用回调,避免了持续轮询带来的高耗电问题。
  4. 不支持主动切换:系统原生能力仅支持通过回调“感知”网络切换,不支持应用主动进行网络切换。

四、 精准识别蜂窝网络代际(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('已强制报告网络连接');
}

底层通信资源管控与避坑

在复杂的网络切换过程中,底层通信资源的管理至关重要,处理不当极易导致内存泄漏或请求异常。

  1. Socket 资源强制释放:当监听到网络切换(如 Wi-Fi 切 5G)或网络丢失时,必须主动关闭旧的 Socket 连接。旧的网络句柄在新的网络环境下已失效,继续持有会导致资源泄漏。
  2. 推荐使用高级通信套件:在多网络频繁切换的场景下,强烈建议使用 @kit.RemoteCommunicationKit 替代原生的 HTTP 模块,它内置了更好的连接池管理和网络异常恢复机制。
  3. 紧急情况下的状态修正:当遇到应用内部记录的网络状态与系统管理器不一致时(例如应用认为已断网,但系统实际可用),可以调用 connection.reportNetDisconnected(badNetHandle) 或 connection.reportNetConnected(goodNetHandle) 强制向系统报告网络状态。
  4. 生命周期严格绑定:网络监听会持续占用系统资源。务必在 EntryAbility 的 onCreate 中开启订阅,在 onWindowStageDestroy 中关闭订阅,防止应用进入后台后仍进行不必要的状态回调。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐