HarmonyOS 网络连接诊断实战:检测网络状态、WiFi 切换、弱网监测一网打尽

引言

App 没网时给个友好提示、网络切换时自动重连、直播时检测弱网降码率------这些能力都靠网络连接诊断。HarmonyOS 的 @ohos.net.connection 模块提供了完整的网络状态监测能力。


一、基础:检测当前网络状态

typescript 复制代码
import connection from '@ohos.net.connection';

1.1 获取网络状态

typescript 复制代码
async function getNetworkState() {
  const netHandle = await connection.getDefaultNet();
  const state = await connection.getNetCapabilities(netHandle);
  
  console.log('网络类型:', state.bearerTypes);    // 例如 [BearerType.CELLULAR]
  console.log('网络能力:', state.networkCapabilities); // 例如 [NET_CAPABILITY_INTERNET]
}

1.2 获取网络类型

typescript 复制代码
// 判断是否有网络
async function isNetworkAvailable(): Promise<boolean> {
  try {
    const netHandle = await connection.getDefaultNet();
    const state = await connection.getNetCapabilities(netHandle);
    return state.bearerTypes.length > 0;
  } catch {
    return false;
  }
}

// 判断当前是 WiFi 还是蜂窝
async function getConnectionType(): Promise<'wifi' | 'cellular' | 'none'> {
  try {
    const netHandle = await connection.getDefaultNet();
    const state = await connection.getNetCapabilities(netHandle);
    
    if (state.bearerTypes.includes(connection.BearerType.WIFI)) return 'wifi';
    if (state.bearerTypes.includes(connection.BearerType.CELLULAR)) return 'cellular';
    return 'none';
  } catch {
    return 'none';
  }
}

二、网络状态实时监听

#mermaid-svg-wMWRlg1OCLXTmPUC{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-wMWRlg1OCLXTmPUC .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-wMWRlg1OCLXTmPUC .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-wMWRlg1OCLXTmPUC .error-icon{fill:#552222;}#mermaid-svg-wMWRlg1OCLXTmPUC .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-wMWRlg1OCLXTmPUC .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-wMWRlg1OCLXTmPUC .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-wMWRlg1OCLXTmPUC .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-wMWRlg1OCLXTmPUC .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-wMWRlg1OCLXTmPUC .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-wMWRlg1OCLXTmPUC .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-wMWRlg1OCLXTmPUC .marker{fill:#333333;stroke:#333333;}#mermaid-svg-wMWRlg1OCLXTmPUC .marker.cross{stroke:#333333;}#mermaid-svg-wMWRlg1OCLXTmPUC svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-wMWRlg1OCLXTmPUC p{margin:0;}#mermaid-svg-wMWRlg1OCLXTmPUC .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-wMWRlg1OCLXTmPUC .cluster-label text{fill:#333;}#mermaid-svg-wMWRlg1OCLXTmPUC .cluster-label span{color:#333;}#mermaid-svg-wMWRlg1OCLXTmPUC .cluster-label span p{background-color:transparent;}#mermaid-svg-wMWRlg1OCLXTmPUC .label text,#mermaid-svg-wMWRlg1OCLXTmPUC span{fill:#333;color:#333;}#mermaid-svg-wMWRlg1OCLXTmPUC .node rect,#mermaid-svg-wMWRlg1OCLXTmPUC .node circle,#mermaid-svg-wMWRlg1OCLXTmPUC .node ellipse,#mermaid-svg-wMWRlg1OCLXTmPUC .node polygon,#mermaid-svg-wMWRlg1OCLXTmPUC .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-wMWRlg1OCLXTmPUC .rough-node .label text,#mermaid-svg-wMWRlg1OCLXTmPUC .node .label text,#mermaid-svg-wMWRlg1OCLXTmPUC .image-shape .label,#mermaid-svg-wMWRlg1OCLXTmPUC .icon-shape .label{text-anchor:middle;}#mermaid-svg-wMWRlg1OCLXTmPUC .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-wMWRlg1OCLXTmPUC .rough-node .label,#mermaid-svg-wMWRlg1OCLXTmPUC .node .label,#mermaid-svg-wMWRlg1OCLXTmPUC .image-shape .label,#mermaid-svg-wMWRlg1OCLXTmPUC .icon-shape .label{text-align:center;}#mermaid-svg-wMWRlg1OCLXTmPUC .node.clickable{cursor:pointer;}#mermaid-svg-wMWRlg1OCLXTmPUC .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-wMWRlg1OCLXTmPUC .arrowheadPath{fill:#333333;}#mermaid-svg-wMWRlg1OCLXTmPUC .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-wMWRlg1OCLXTmPUC .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-wMWRlg1OCLXTmPUC .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wMWRlg1OCLXTmPUC .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-wMWRlg1OCLXTmPUC .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wMWRlg1OCLXTmPUC .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-wMWRlg1OCLXTmPUC .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-wMWRlg1OCLXTmPUC .cluster text{fill:#333;}#mermaid-svg-wMWRlg1OCLXTmPUC .cluster span{color:#333;}#mermaid-svg-wMWRlg1OCLXTmPUC div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-wMWRlg1OCLXTmPUC .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-wMWRlg1OCLXTmPUC rect.text{fill:none;stroke-width:0;}#mermaid-svg-wMWRlg1OCLXTmPUC .icon-shape,#mermaid-svg-wMWRlg1OCLXTmPUC .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wMWRlg1OCLXTmPUC .icon-shape p,#mermaid-svg-wMWRlg1OCLXTmPUC .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-wMWRlg1OCLXTmPUC .icon-shape .label rect,#mermaid-svg-wMWRlg1OCLXTmPUC .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wMWRlg1OCLXTmPUC .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-wMWRlg1OCLXTmPUC .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-wMWRlg1OCLXTmPUC :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} WiFi断开
网络恢复
质量变化
注册监听
on netCapabilitiesChange
网络变化
切换到蜂窝/显示提示
重试未完成的请求
调整应用行为

2.1 网络能力变化监听

typescript 复制代码
aboutToAppear() {
  connection.on('netCapabilitiesChange', async (netHandle) => {
    const state = await connection.getNetCapabilities(netHandle);
    const hasInternet = state.networkCapabilities.includes(
      connection.NetCap.NET_CAPABILITY_INTERNET
    );
    
    if (hasInternet) {
      this.networkStatus = '已连接';
      this.retryFailedRequests(); // 重试失败的请求
    } else {
      this.networkStatus = '无网络';
      this.showNetworkError();
    }
  });
}

2.2 网络连接/断开监听

typescript 复制代码
// WiFi 连接/断开
connection.on('netAvailable', (netHandle) => {
  console.log('网络可用:', netHandle.netId);
});

connection.on('netLost', (netHandle) => {
  console.log('网络丢失:', netHandle.netId);
});

// 连接状态变化(更细粒度)
connection.on('netStateChange', (data) => {
  console.log('是否WiFi:', data.isWifi);
  console.log('是否蜂窝:', data.isCellular);
  console.log('是否有网络:', data.isAvailable);
});

三、网络地址与 DNS 查询

3.1 获取 IP 地址

typescript 复制代码
async function getLocalIp(): Promise<string[]> {
  const netHandle = await connection.getDefaultNet();
  const addrs = await connection.getAddressesByName(netHandle, 'localhost');
  return addrs.map(a => a.address.address);
}

3.2 DNS 解析

typescript 复制代码
async function dnsLookup(host: string): Promise<string[]> {
  const netHandle = await connection.getDefaultNet();
  const addrs = await connection.getAddressesByName(netHandle, host);
  return addrs.map(a => `${a.address.address}:${a.port}`);
}

// 使用
dnsLookup('api.example.com').then(addrs => {
  console.log('DNS解析结果:', addrs); // ['203.0.113.5:0', '2401:xxxx::1:0']
});

3.3 获取网络代理信息

typescript 复制代码
async function getProxyInfo() {
  const netHandle = await connection.getDefaultNet();
  const proxy = await connection.getDefaultHttpProxy();
  console.log('代理主机:', proxy.host);
  console.log('代理端口:', proxy.port);
  console.log('排除列表:', proxy.exclusionList);
}

四、实战:网络诊断工具

typescript 复制代码
class NetworkDiagnostics {
  private isOnline: boolean = false;
  private currentType: string = 'none';

  async init() {
    try {
      const netHandle = await connection.getDefaultNet();
      const state = await connection.getNetCapabilities(netHandle);
      this.isOnline = state.networkCapabilities.includes(
        connection.NetCap.NET_CAPABILITY_INTERNET
      );
      this.updateType(state);
    } catch {
      this.isOnline = false;
    }
    
    this.startListening();
  }

  private updateType(state: connection.NetCap) {
    if (state.bearerTypes.includes(connection.BearerType.WIFI)) {
      this.currentType = 'WiFi';
    } else if (state.bearerTypes.includes(connection.BearerType.CELLULAR)) {
      this.currentType = '蜂窝网络';
    } else {
      this.currentType = '其他';
    }
  }

  private startListening() {
    connection.on('netCapabilitiesChange', async (handle) => {
      const state = await connection.getNetCapabilities(handle);
      this.isOnline = state.networkCapabilities.includes(
        connection.NetCap.NET_CAPABILITY_INTERNET
      );
      this.updateType(state);
      console.log(`网络更新: ${this.currentType}, 在线: ${this.isOnline}`);
    });
  }

  getStatus() {
    return {
      online: this.isOnline,
      type: this.currentType
    };
  }

  destroy() {
    connection.off('netCapabilitiesChange');
    connection.off('netAvailable');
    connection.off('netLost');
  }
}

// 使用
const diag = new NetworkDiagnostics();
diag.init();

五、弱网检测与应对策略

typescript 复制代码
// 检测弱网并降低资源消耗
class WeakNetworkHandler {
  private isWeakNetwork: boolean = false;
  private checkInterval: number = 3000; // 3秒检测一次

  async startMonitoring() {
    setInterval(async () => {
      try {
        const netHandle = await connection.getDefaultNet();
        const state = await connection.getNetCapabilities(netHandle);
        
        // 如果没有 INTERNET 能力或只有蜂窝(通常比WiFi慢),认为是弱网
        const hasInternet = state.networkCapabilities.includes(
          connection.NetCap.NET_CAPABILITY_INTERNET
        );
        const isCellularOnly = 
          state.bearerTypes.includes(connection.BearerType.CELLULAR) &&
          !state.bearerTypes.includes(connection.BearerType.WIFI);
        
        this.isWeakNetwork = !hasInternet || isCellularOnly;
        
        if (this.isWeakNetwork) {
          console.log('弱网环境,切换为低资源模式');
          // 降低图片质量
          // 减少预加载
          // 增加超时时间
        }
      } catch {
        this.isWeakNetwork = true;
      }
    }, this.checkInterval);
  }

  shouldLoadHDContent(): boolean {
    return !this.isWeakNetwork;
  }
}

六、API 速查表

API 说明 异步
getDefaultNet() 获取默认网络
getNetCapabilities(handle) 获取网络能力
getAddressesByName(handle, host) DNS解析
getDefaultHttpProxy() 获取代理
on('netAvailable') 网络可用监听 -
on('netLost') 网络丢失监听 -
on('netCapabilitiesChange') 网络能力变化 -
on('netStateChange') 网络状态变化 -
off(event) 移除监听 -
BearerType 说明
WIFI WiFi网络
CELLULAR 蜂窝网络
ETHERNET 以太网
BLUETOOTH 蓝牙
NetCap 说明
NET_CAPABILITY_INTERNET 可访问互联网
NET_CAPABILITY_NOT_METERED 非计费网络(如WiFi)
NET_CAPABILITY_NOT_VPN 非VPN连接

总结

#mermaid-svg-yMOBWnUrboG5lHe2{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-yMOBWnUrboG5lHe2 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yMOBWnUrboG5lHe2 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yMOBWnUrboG5lHe2 .error-icon{fill:#552222;}#mermaid-svg-yMOBWnUrboG5lHe2 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yMOBWnUrboG5lHe2 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yMOBWnUrboG5lHe2 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yMOBWnUrboG5lHe2 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yMOBWnUrboG5lHe2 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yMOBWnUrboG5lHe2 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yMOBWnUrboG5lHe2 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yMOBWnUrboG5lHe2 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yMOBWnUrboG5lHe2 .marker.cross{stroke:#333333;}#mermaid-svg-yMOBWnUrboG5lHe2 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yMOBWnUrboG5lHe2 p{margin:0;}#mermaid-svg-yMOBWnUrboG5lHe2 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-yMOBWnUrboG5lHe2 .cluster-label text{fill:#333;}#mermaid-svg-yMOBWnUrboG5lHe2 .cluster-label span{color:#333;}#mermaid-svg-yMOBWnUrboG5lHe2 .cluster-label span p{background-color:transparent;}#mermaid-svg-yMOBWnUrboG5lHe2 .label text,#mermaid-svg-yMOBWnUrboG5lHe2 span{fill:#333;color:#333;}#mermaid-svg-yMOBWnUrboG5lHe2 .node rect,#mermaid-svg-yMOBWnUrboG5lHe2 .node circle,#mermaid-svg-yMOBWnUrboG5lHe2 .node ellipse,#mermaid-svg-yMOBWnUrboG5lHe2 .node polygon,#mermaid-svg-yMOBWnUrboG5lHe2 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-yMOBWnUrboG5lHe2 .rough-node .label text,#mermaid-svg-yMOBWnUrboG5lHe2 .node .label text,#mermaid-svg-yMOBWnUrboG5lHe2 .image-shape .label,#mermaid-svg-yMOBWnUrboG5lHe2 .icon-shape .label{text-anchor:middle;}#mermaid-svg-yMOBWnUrboG5lHe2 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-yMOBWnUrboG5lHe2 .rough-node .label,#mermaid-svg-yMOBWnUrboG5lHe2 .node .label,#mermaid-svg-yMOBWnUrboG5lHe2 .image-shape .label,#mermaid-svg-yMOBWnUrboG5lHe2 .icon-shape .label{text-align:center;}#mermaid-svg-yMOBWnUrboG5lHe2 .node.clickable{cursor:pointer;}#mermaid-svg-yMOBWnUrboG5lHe2 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-yMOBWnUrboG5lHe2 .arrowheadPath{fill:#333333;}#mermaid-svg-yMOBWnUrboG5lHe2 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-yMOBWnUrboG5lHe2 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-yMOBWnUrboG5lHe2 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yMOBWnUrboG5lHe2 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-yMOBWnUrboG5lHe2 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yMOBWnUrboG5lHe2 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-yMOBWnUrboG5lHe2 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-yMOBWnUrboG5lHe2 .cluster text{fill:#333;}#mermaid-svg-yMOBWnUrboG5lHe2 .cluster span{color:#333;}#mermaid-svg-yMOBWnUrboG5lHe2 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-yMOBWnUrboG5lHe2 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-yMOBWnUrboG5lHe2 rect.text{fill:none;stroke-width:0;}#mermaid-svg-yMOBWnUrboG5lHe2 .icon-shape,#mermaid-svg-yMOBWnUrboG5lHe2 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yMOBWnUrboG5lHe2 .icon-shape p,#mermaid-svg-yMOBWnUrboG5lHe2 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-yMOBWnUrboG5lHe2 .icon-shape .label rect,#mermaid-svg-yMOBWnUrboG5lHe2 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yMOBWnUrboG5lHe2 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-yMOBWnUrboG5lHe2 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-yMOBWnUrboG5lHe2 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} WiFi
蜂窝
无网络
connection.on监听网络变化
网络类型?
加载高清内容
降低流量消耗
显示离线状态/缓存数据
netCapabilitiesChange

实时更新

网络连接诊断是App体验的隐形护城河------好的App会在网络变化时无声地处理好一切,用户甚至不会察觉到。

相关推荐
CPETW44 分钟前
USB TO I2C_(Excel)_Scan ---- 1000KHz总线速率测试_A
c语言·开发语言·网络·科技·单片机
贾伟康1 小时前
【天体运行模拟|08】HarmonyOS ArkTS 单位换算实战:处理天文尺度、科学计数与精度
harmonyos·arkts·arkui·数值精度·单位换算
杨云龙UP1 小时前
Oracle 19c RMAN历史备份清理失败:CONTROL_FILE_RECORD_KEEP_TIME 问题排查与整改实战
linux·运维·网络·数据库·oracle·rac
2501_919749032 小时前
华为鸿蒙免费反诈APP—小羊反诈
华为·harmonyos·鸿蒙
pt10432 小时前
网络自动化Python课程:Netconf与Restconf及Cisco自动化配置实验
网络·python·自动化
2501_919749032 小时前
华为鸿蒙免费视频播放器—小羊免费播放器
华为·harmonyos·鸿蒙
神仙别闹2 小时前
基于C++ WinPcap 的网络抓包软件
网络·c++·php
LabVIEW开发2 小时前
使用 LabVIEW 获取文件的创建日期:从内置函数到 Windows API 封装
网络·windows·labview·labview知识·labview功能·labview程序
DevOpenClub3 小时前
全球区域与 IP 定位工作台案例方案
大数据·网络·网络协议·tcp/ip