鸿蒙 ArkTS 实战:从零实现网络质量检测与评分功能

发布于:2025-09-16 ⋅ 阅读:(21) ⋅ 点赞:(0)

鸿蒙 ArkTS 实战:从零实现网络质量检测与评分功能

在移动应用开发中,网络质量直接影响用户体验 —— 无论是视频播放、文件下载还是实时交互,都需要根据网络状况调整功能策略。鸿蒙系统(HarmonyOS)作为面向全场景的分布式操作系统,提供了完善的网络 API 支持,这篇文章我就分享一下如何从零开始,基于 ArkTS 实现一套可直接落地的网络质量检测方案,通过测速数据将网络状态量化为 “差、中、好” 三个等级,为应用进行优化提升。

一、核心原理与实现思路

网络质量检测的本质是通过 “状态判断 + 性能测试” 双维度评估网络状况:

状态判断:先通过鸿蒙网络 API 获取当前网络类型(WiFi / 移动数据 / 无网络),排除无网络场景;

性能测试:通过请求固定大小的测试资源,计算下载速度(单位:KB/s);

等级划分:根据实际应用场景设定速度阈值,将网络质量映射为 “差、中、好” 三个等级。

整个实现流程需经历 “权限申请→网络状态检测→测速逻辑实现→结果评分→UI 展示” 五个核心步骤,下文将逐一拆解每个环节的具体代码与注意事项。

二、前置准备:权限配置与依赖引入

大家注意哦,鸿蒙系统对敏感权限管控严格,网络检测需申请两个核心权限:INTERNET(网络访问权限)和GET_NETWORK_INFO(获取网络状态权限),需在配置文件中提前声明。

1. 配置 module.json5 权限

在 entry 模块的module.json5文件中,添加权限声明(路径:entry/src/main/module.json5):

{
  "module": {
    // 其他配置省略...
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET",
        "reason": "需要访问网络以进行测速",
        "usedScene": {
          "ability": ["EntryAbility"],
          "when": "always"
        }
      },
      {
        "name": "ohos.permission.GET_NETWORK_INFO",
        "reason": "需要获取当前网络类型(WiFi/移动数据)",
        "usedScene": {
          "ability": ["EntryAbility"],
          "when": "always"
        }
      }
    ]
  }
}

注意:reason字段需明确说明权限用途,鸿蒙应用市场审核时会校验权限申请的合理性;usedScene指定权限生效的能力与时机,避免过度授权。

2. 引入核心 API 依赖

网络检测需用到鸿蒙的@ohos.net.network(网络状态)和@ohos.net.http(HTTP 请求)模块,在代码文件顶部引入:

import network from '@ohos.net.network';
import http from '@ohos.net.http';
import { BusinessError } from '@ohos.base';

三、核心功能实现:网络检测工具类

为提高代码复用性,我们封装一个NetworkQualityManager工具类,集中管理 “网络状态检测、测速、评分” 三大核心能力,避免业务代码与工具逻辑耦合。

1. 工具类整体结构

/**
 * 网络质量检测工具类
 * 功能:获取网络类型、检测网络速度、评定网络质量等级
 */
export class NetworkQualityManager {
  // 测试资源地址(建议选择稳定的CDN资源,大小100KB左右)
  private static TEST_RESOURCE_URL = 'https://example.com/test-resource-100kb.txt';
  
  // 网络质量等级阈值(单位:KB/s,可根据业务调整)
  private static QUALITY_THRESHOLD = {
    POOR: 50,    // 差:低于50KB/s
    MODERATE: 200 // 中:50-200KB/s;好:高于200KB/s
  };

  /**
   * 1. 检查当前网络是否可用
   * @returns Promise<boolean> 网络是否可用
   */
  public static async isNetworkAvailable(): Promise<boolean> {
    try {
      // 获取默认网络的状态
      const networkStatus = await network.getCurrentNetworkStatus();
      return networkStatus.isAvailable;
    } catch (error) {
      const err = error as BusinessError;
      console.error(`检查网络可用性失败:${err.code} - ${err.message}`);
      return false;
    }
  }

  /**
   * 2. 获取当前网络类型
   * @returns Promise<string> 网络类型(如:WiFi、移动数据、无网络)
   */
  public static async getNetworkType(): Promise<string> {
    if (!await this.isNetworkAvailable()) {
      return '无网络';
    }

    try {
      const networkType = await network.getNetworkType();
      switch (networkType) {
        case network.NetworkType.NETWORK_TYPE_WIFI:
          return 'WiFi';
        case network.NetworkType.NETWORK_TYPE_MOBILE:
          return '移动数据(4G/5G)';
        case network.NetworkType.NETWORK_TYPE_ETHERNET:
          return '以太网';
        default:
          return '未知网络';
      }
    } catch (error) {
      const err = error as BusinessError;
      console.error(`获取网络类型失败:${err.code} - ${err.message}`);
      return '获取失败';
    }
  }

  /**
   * 3. 核心:检测网络下载速度
   * 原理:请求固定大小的测试资源,计算耗时与速度
   * @returns Promise<number> 下载速度(单位:KB/s)
   */
  public static async testDownloadSpeed(): Promise<number> {
    if (!await this.isNetworkAvailable()) {
      throw new Error('当前无可用网络,无法测速');
    }

    const httpRequest = http.createHttp();
    let startTime: number, endTime: number;

    try {
      // 记录开始时间(毫秒级)
      startTime = Date.now();
      
      // 发送GET请求获取测试资源(禁用缓存,确保真实测速)
      const response = await httpRequest.request(this.TEST_RESOURCE_URL, {
        method: http.RequestMethod.GET,
        header: {
          'Cache-Control': 'no-cache' // 禁用缓存,避免本地缓存影响测速结果
        },
        readTimeout: 5000, // 读取超时:5秒
        connectTimeout: 3000 // 连接超时:3秒
      });

      // 校验请求结果
      if (response.responseCode !== 200) {
        throw new Error(`请求测试资源失败,状态码:${response.responseCode}`);
      }

      // 记录结束时间
      endTime = Date.now();
      // 计算耗时(秒):(结束时间-开始时间)/1000
      const costTime = (endTime - startTime) / 1000;
      // 计算下载速度(KB/s):资源大小(字节)/ 1024 / 耗时(秒)
      // 注:response.result为ArrayBuffer类型,byteLength获取字节数
      const resourceSize = (response.result as ArrayBuffer).byteLength;
      const speed = (resourceSize / 1024) / costTime;

      return Math.round(speed); // 四舍五入取整,简化展示
    } catch (error) {
      const err = error as BusinessError;
      console.error(`测速失败:${err.message || err.code}`);
      throw new Error(`测速失败:${err.message || '未知错误'}`);
    } finally {
      // 销毁HTTP请求,避免内存泄漏
      httpRequest.destroy();
    }
  }

  /**
   * 4. 根据速度评定网络质量等级
   * @param speed 下载速度(KB/s)
   * @returns {level: string, color: string} 等级与对应颜色(用于UI展示)
   */
  public static getQualityLevel(speed: number): { level: string; color: string } {
    if (speed < this.QUALITY_THRESHOLD.POOR) {
      return { level: '差', color: '#FF4444' }; // 红色:差
    } else if (speed <= this.QUALITY_THRESHOLD.MODERATE) {
      return { level: '中', color: '#FFCC00' }; // 黄色:中
    } else {
      return { level: '好', color: '#00CC66' }; // 绿色:好
    }
  }

  /**
   * 对外暴露:一键获取完整网络质量信息
   * @returns 包含网络类型、速度、等级的完整数据
   */
  public static async getNetworkQuality(): Promise<{
    type: string;
    speed: number;
    level: string;
    color: string;
  }> {
    const type = await this.getNetworkType();
    if (type === '无网络') {
      return { type, speed: 0, level: '无', color: '#999999' };
    }
    const speed = await this.testDownloadSpeed();
    const { level, color } = this.getQualityLevel(speed);
    return { type, speed, level, color };
  }
}

2. 关键细节说明

  • 测试资源选择:TEST_RESOURCE_URL建议选择大小 100KB-1MB 的静态资源(如 txt、图片),过小会导致测速误差大,过大则耗时久;推荐使用阿里云、腾讯云等 CDN 节点,确保资源稳定性。
  • 超时控制:readTimeout和connectTimeout分别设置为 5 秒和 3 秒,避免弱网环境下长时间阻塞;
  • 缓存处理:通过Cache-Control: no-cache禁用 HTTP 缓存,防止本地缓存的资源影响真实测速结果;
  • 异常处理:每个异步方法都包含错误捕获,确保单点故障不影响整体功能,同时输出详细错误日志便于调试。

四、UI 层集成:可视化展示网络质量

工具类实现后,需在 UI 页面中调用接口并展示结果。以下是基于 ArkTS 声明式 UI 的示例,包含 “网络类型、速度、质量等级” 展示,以及 “重新检测” 按钮。

1. 页面代码实现

import { NetworkQualityManager } from '../utils/NetworkQualityManager';
import { useState, useEffect } from '@ohos/base';

@Entry
@Component
struct NetworkQualityPage {
  // 状态管理:网络质量数据、加载状态、错误信息
  @State networkQuality = {
    type: '检测中...',
    speed: 0,
    level: '待检测',
    color: '#999999'
  };
  @State isLoading: boolean = false;
  @State errorMsg: string = '';

  /**
   * 页面加载时自动检测一次网络质量
   */
  useEffect(() => {
    this.detectNetworkQuality();
  }, []);

  /**
   * 调用工具类检测网络质量
   */
  private async detectNetworkQuality() {
    this.isLoading = true;
    this.errorMsg = '';
    try {
      const result = await NetworkQualityManager.getNetworkQuality();
      this.networkQuality = result;
    } catch (error) {
      this.errorMsg = (error as Error).message;
      // 错误状态下重置展示数据
      this.networkQuality = {
        type: '获取失败',
        speed: 0,
        level: '无',
        color: '#999999'
      };
    } finally {
      this.isLoading = false;
    }
  }

  build() {
    Column({ space: 20 }) {
      // 页面标题
      Text('当前网络质量')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 50 });

      // 加载状态提示
      if (this.isLoading) {
        Progress({ value: 50, type: ProgressType.Circular })
          .width(40)
          .height(40);
        Text('正在测速中...')
          .fontSize(16)
          .color('#666666');
      } else {
        // 网络类型展示
        Text(`网络类型:${this.networkQuality.type}`)
          .fontSize(18)
          .color('#333333');

        // 网络速度展示
        Text(`下载速度:${this.networkQuality.speed} KB/s`)
          .fontSize(18)
          .color('#333333');

        // 网络质量等级(带颜色标识)
        Text(`网络质量:${this.networkQuality.level}`)
          .fontSize(20)
          .fontWeight(FontWeight.Bold)
          .color(this.networkQuality.color);

        // 错误信息展示
        if (this.errorMsg) {
          Text(`错误:${this.errorMsg}`)
            .fontSize(16)
            .color('#FF4444')
            .margin({ top: 10 });
        }
      }

      // 重新检测按钮
      Button('重新检测网络')
        .width(200)
        .height(45)
        .fontSize(16)
        .backgroundColor('#007AFF')
        .margin({ top: 30 })
        .onClick(() => {
          this.detectNetworkQuality();
        });
    }
    .width('100%')
    .padding(20)
  }
}

2. UI 交互设计要点

  • 加载状态反馈:测速过程中显示圆形进度条,避免用户误以为页面无响应;
  • 颜色可视化:用 “红、黄、绿” 三色区分网络质量,符合用户认知习惯;
  • 错误友好提示:当测速失败时(如网络断开、资源不可用),显示具体错误信息,便于用户排查问题;
  • 手动触发机制:提供 “重新检测” 按钮,支持用户主动更新网络质量数据。

五、功能优化与扩展建议

基础版本实现后,可根据业务需求进行以下优化,提升功能实用性与稳定性:

1. 动态调整测试资源

不同场景下对测速精度要求不同:

  • 弱网场景:选择 50KB 小资源,减少测速耗时;
  • 高速网络(如 5G/WiFi):选择 1MB 大资源,避免因资源过小导致速度计算误差。

可在工具类中添加资源切换逻辑:

// 根据网络类型动态选择测试资源
private static getTestResourceUrl(networkType: string): string {
  if (networkType.includes('移动数据')) {
    return 'https://example.com/test-resource-50kb.txt'; // 移动数据用小资源
  } else {
    return 'https://example.com/test-resource-1mb.txt';  // WiFi用大资源
  }
}

2. 多次测速取平均值

单次测速易受网络波动影响,可增加 “多次测试取平均” 逻辑,提升结果准确性:

/**
 * 多次测速取平均值(默认3次)
 */
public static async testSpeedWithAverage(count: number = 3): Promise<number> {
  if (count < 1) count = 1;
  let totalSpeed = 0;
  let validCount = 0;

  for (let i = 0; i < count; i++) {
    try {
      const speed = await this.testDownloadSpeed();
      totalSpeed += speed;
      validCount++;
    } catch (error) {
      console.warn(`第${i+1}次测速失败,跳过:${(error as Error).message}`);
    }
  }

  if (validCount === 0) throw new Error('所有测速尝试均失败');
  return Math.round(totalSpeed / validCount);
}

3. 适配分布式场景

鸿蒙系统支持多设备协同,可扩展功能实现 “跨设备网络质量检测”,例如:

  • 在手机端检测当前网络,同步到平板端;
  • 根据不同设备的网络状况,推荐最优设备执行高带宽任务(如下载)。

六、常见问题与解决方案

权限申请被拒绝:需在代码中检查权限授予状态,若被拒绝则引导用户前往设置页开启:

import abilityAccessCtrl from '@ohos.abilityAccessCtrl';

// 检查权限是否授予
public static async checkPermission(permission: string): Promise<boolean> {
  const atManager = abilityAccessCtrl.createAtManager();
  const result = await atManager.checkAccessToken(abilityAccessCtrl.createTokenID(), permission);
  return result === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
}

测试资源不可用:建议配置多个备用测试资源地址,当一个地址请求失败时自动切换到下一个:

private static TEST_RESOURCE_URLS = [
  'https://example1.com/test.txt',
  'https://example2.com/test.txt'
];

弱网下测速超时:可动态调整超时时间,弱网场景下适当延长readTimeout(如 10 秒)。

总结

这里分享了基于鸿蒙 ArkTS 实现了一套完整的网络质量检测方案,核心是通过 “状态判断 + 速度测试” 实现量化评分,并通过工具类封装提高代码复用性。该方案可直接应用于视频、下载、社交等需要网络质量感知的场景,帮助开发者根据网络状况优化功能策略(如弱网下降低视频清晰度、暂停自动下载等),最终提升用户体验。后续可结合鸿蒙的分布式能力与场景化需求,进一步扩展功能,例如添加上传速度检测、网络延迟测试(ping)等,构建更全面的网络质量评估体系。

希望文章对大家有所帮助。