HarmonyOS 6学习:网络能力变化监听与智能提示——告别流量偷跑,打造贴心网络感知应用

引言:当你的应用在用户不知情时"偷跑"流量

想象这样一个场景:用户在地铁上使用你的视频应用观看高清电影,享受着流畅的观影体验。当地铁进入隧道,Wi-Fi信号突然中断,手机自动切换到移动数据网络。用户对此毫不知情,继续观看电影。几分钟后,他收到运营商的短信:"您的本月流量已用尽,超额流量费用50元"。

用户愤怒地打开流量统计,发现你的应用在短短几分钟内消耗了数百MB流量。他开始怀疑:"是这个应用有问题,还是我的手机设置不对?"最终,他可能选择卸载应用,并在应用商店留下差评:"偷跑流量,垃圾应用!"

这种"网络切换无感知"的问题在很多应用中普遍存在,但往往被开发者忽视。用户从Wi-Fi切换到移动数据时,应用没有给出任何提示,继续以高清质量加载内容,导致流量快速消耗。本文将带你深入HarmonyOS网络能力监听机制,揭秘如何打造智能网络感知应用,让用户对网络切换了如指掌。

一、问题重现:流量"偷跑"的案发现场

1.1 典型问题现象

用户正常使用场景

  • 在Wi-Fi环境下打开视频应用,观看高清视频

  • 应用流畅加载,无卡顿,用户体验良好

  • 用户放心观看,不考虑流量消耗

网络切换时的问题

  • Wi-Fi信号中断,设备自动切换到移动数据

  • 应用没有任何提示,继续以高清质量加载视频

  • 用户继续观看,完全不知道正在使用移动流量

  • 几分钟后,流量告警短信到来,用户才发现问题

1.2 问题影响范围

应用类型 网络敏感度 流量消耗风险 用户影响程度
视频流媒体 极高 极高(每分钟10-50MB) 极高
音乐/播客 高(每分钟1-5MB)
地图导航 中(实时路况、地图下载) 中高
云存储同步 高(大文件上传下载)
新闻资讯 低(文字+缩略图)

二、技术原理:为什么应用对网络切换"视而不见"?

2.1 网络能力监听的核心机制

要理解这个问题,首先需要掌握HarmonyOS网络能力监听的两个关键API:

1. getNetCapabilities() - 获取当前网络能力

  • 同步方法,立即返回当前网络状态

  • 可以获取网络类型(Wi-Fi、蜂窝数据、以太网等)

  • 可以获取网络能力(是否计费、是否漫游等)

  • 通常在应用启动时调用,获取初始网络状态

2. on('netCapabilitiesChange') - 监听网络能力变化

  • 异步事件监听,当网络状态变化时触发

  • 实时响应网络切换、信号强度变化等

  • 可以获取变化前后的网络能力对比

  • 是避免"流量偷跑"的关键监听器

2.2 问题的根本原因

根据华为官方文档的分析,问题的核心在于:大多数应用只在启动时获取一次网络状态,但没有持续监听网络变化。当网络从Wi-Fi切换到移动数据时,应用无法感知,继续以Wi-Fi环境下的策略运行。

简单来说

  • 应用启动时:检测到Wi-Fi,启用高清模式

  • Wi-Fi断开时:应用不知道网络已切换

  • 切换到移动数据:应用继续使用高清模式

  • 结果:大量流量被消耗,用户毫不知情

网络状态变化流程

复制代码
Wi-Fi连接正常 → 应用使用高清策略
    ↓
Wi-Fi信号中断 → 系统自动切换网络
    ↓
移动数据连接 → 应用仍使用高清策略(问题所在)
    ↓
流量快速消耗 → 用户收到超额账单

三、实战解决方案:三步实现智能网络感知

3.1 解决方案总览

解决"流量偷跑"问题的核心思路:实时监听网络能力变化,在网络切换时及时调整应用行为并通知用户

复制代码
graph TD
    A[问题: 网络切换无感知导致流量偷跑] --> B{根本原因分析}
    B --> C[应用未监听网络变化]
    C --> D[解决方案]
    D --> E[步骤1: 初始化网络监听]
    D --> F[步骤2: 实时响应变化]
    D --> G[步骤3: 智能策略调整]
    E --> H[贴心网络感知应用]
    F --> H
    G --> H

3.2 步骤一:完整的网络能力监听器实现

首先需要创建一个完整的网络能力监听器,覆盖所有网络状态变化场景。

复制代码
// NetworkMonitor.ets - 智能网络监听管理器
import { common } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import connection from '@kit.NetConnectionKit';

export class NetworkMonitor {
  private static instance: NetworkMonitor;
  private netHandle: connection.NetConnection | null = null;
  private currentNetCapabilities: connection.NetCapabilities | null = null;
  private listeners: NetworkChangeCallback[] = [];
  
  // 网络类型枚举
  static NetworkType = {
    UNKNOWN: 'unknown',
    WIFI: 'wifi',
    CELLULAR: 'cellular',
    ETHERNET: 'ethernet',
    BLUETOOTH: 'bluetooth',
    VPN: 'vpn',
    WIFI_AWARE: 'wifi_aware',
    LOWPAN: 'lowpan'
  };
  
  // 网络能力枚举
  static NetCapability = {
    INTERNET: 1,           // 可访问互联网
    NOT_METERED: 2,        // 不计费网络
    NOT_ROAMING: 3,        // 非漫游状态
    VALIDATED: 4,          // 网络已验证
    NOT_CONGESTED: 5,      // 网络不拥塞
    NOT_SUSPENDED: 6       // 网络未挂起
  };
  
  // 网络变化回调类型
  type NetworkChangeCallback = (
    oldCapabilities: connection.NetCapabilities | null,
    newCapabilities: connection.NetCapabilities,
    changeType: string
  ) => void;
  
  // 单例模式
  private constructor() {}
  
  static getInstance(): NetworkMonitor {
    if (!NetworkMonitor.instance) {
      NetworkMonitor.instance = new NetworkMonitor();
    }
    return NetworkMonitor.instance;
  }
  
  // 初始化网络监听
  async initialize(): Promise<boolean> {
    try {
      // 创建网络连接实例
      this.netHandle = connection.createNetConnection();
      
      if (!this.netHandle) {
        console.error('创建网络连接实例失败');
        return false;
      }
      
      // 获取初始网络能力
      await this.updateCurrentNetCapabilities();
      
      // 监听网络能力变化
      this.setupNetCapabilitiesListener();
      
      // 监听网络连接状态变化
      this.setupConnectionStateListener();
      
      console.info('网络监听器初始化成功');
      return true;
      
    } catch (err) {
      const error = err as BusinessError;
      console.error(`网络监听器初始化失败: ${error.code}, ${error.message}`);
      return false;
    }
  }
  
  // 获取当前网络能力
  private async updateCurrentNetCapabilities(): Promise<void> {
    try {
      if (!this.netHandle) {
        return;
      }
      
      const capabilities = await this.netHandle.getNetCapabilities();
      const oldCapabilities = this.currentNetCapabilities;
      this.currentNetCapabilities = capabilities;
      
      // 如果是首次获取,通知监听器
      if (!oldCapabilities && capabilities) {
        this.notifyListeners(null, capabilities, 'INITIAL');
      }
      
      console.info('当前网络能力更新:', this.formatCapabilities(capabilities));
      
    } catch (err) {
      const error = err as BusinessError;
      console.error(`获取网络能力失败: ${error.code}, ${error.message}`);
    }
  }
  
  // 设置网络能力变化监听
  private setupNetCapabilitiesListener(): void {
    if (!this.netHandle) {
      return;
    }
    
    this.netHandle.on('netCapabilitiesChange', (data: connection.NetCapabilitiesChangeData) => {
      console.info('网络能力发生变化');
      
      const oldCapabilities = this.currentNetCapabilities;
      const newCapabilities = data.netCapabilities;
      
      // 更新当前网络能力
      this.currentNetCapabilities = newCapabilities;
      
      // 分析变化类型
      const changeType = this.analyzeChangeType(oldCapabilities, newCapabilities);
      
      // 通知所有监听器
      this.notifyListeners(oldCapabilities, newCapabilities, changeType);
      
      // 记录变化日志
      this.logNetworkChange(oldCapabilities, newCapabilities, changeType);
    });
  }
  
  // 设置网络连接状态监听
  private setupConnectionStateListener(): void {
    if (!this.netHandle) {
      return;
    }
    
    this.netHandle.on('connectionStateChange', (data: { state: number }) => {
      const state = data.state;
      let stateText = '';
      
      switch (state) {
        case connection.ConnectionState.CONNECTING:
          stateText = '连接中';
          break;
        case connection.ConnectionState.CONNECTED:
          stateText = '已连接';
          break;
        case connection.ConnectionState.DISCONNECTING:
          stateText = '断开中';
          break;
        case connection.ConnectionState.DISCONNECTED:
          stateText = '已断开';
          break;
        case connection.ConnectionState.UNAVAILABLE:
          stateText = '不可用';
          break;
        default:
          stateText = '未知状态';
      }
      
      console.info(`网络连接状态变化: ${stateText}(${state})`);
      
      // 连接状态变化时,重新获取网络能力
      if (state === connection.ConnectionState.CONNECTED) {
        this.updateCurrentNetCapabilities();
      }
    });
  }
  
  // 分析网络变化类型
  private analyzeChangeType(
    oldCapabilities: connection.NetCapabilities | null,
    newCapabilities: connection.NetCapabilities
  ): string {
    if (!oldCapabilities) {
      return 'INITIAL';
    }
    
    // 检查网络类型变化
    const oldTypes = oldCapabilities.bearerTypes;
    const newTypes = newCapabilities.bearerTypes;
    
    const hadWifi = oldTypes.includes(connection.NetBearType.BEARER_WIFI);
    const hasWifi = newTypes.includes(connection.NetBearType.BEARER_WIFI);
    
    const hadCellular = oldTypes.includes(connection.NetBearType.BEARER_CELLULAR);
    const hasCellular = newTypes.includes(connection.NetBearType.BEARER_CELLULAR);
    
    // Wi-Fi ↔ 移动数据切换
    if (hadWifi && !hasWifi && hasCellular) {
      return 'WIFI_TO_CELLULAR';
    }
    
    if (!hadWifi && hasWifi && hadCellular) {
      return 'CELLULAR_TO_WIFI';
    }
    
    // 计费状态变化
    const oldMetered = oldCapabilities.netCapabilities.includes(
      connection.NetCap.NET_CAPABILITY_NOT_METERED
    );
    const newMetered = newCapabilities.netCapabilities.includes(
      connection.NetCap.NET_CAPABILITY_NOT_METERED
    );
    
    if (oldMetered !== newMetered) {
      return newMetered ? 'METERED_TO_UNMETERED' : 'UNMETERED_TO_METERED';
    }
    
    // 漫游状态变化
    const oldRoaming = oldCapabilities.netCapabilities.includes(
      connection.NetCap.NET_CAPABILITY_NOT_ROAMING
    );
    const newRoaming = newCapabilities.netCapabilities.includes(
      connection.NetCap.NET_CAPABILITY_NOT_ROAMING
    );
    
    if (oldRoaming !== newRoaming) {
      return newRoaming ? 'ROAMING_TO_HOME' : 'HOME_TO_ROAMING';
    }
    
    return 'OTHER_CHANGE';
  }
  
  // 通知所有监听器
  private notifyListeners(
    oldCapabilities: connection.NetCapabilities | null,
    newCapabilities: connection.NetCapabilities,
    changeType: string
  ): void {
    this.listeners.forEach(listener => {
      try {
        listener(oldCapabilities, newCapabilities, changeType);
      } catch (err) {
        console.error('网络变化监听器执行失败:', err);
      }
    });
  }
  
  // 记录网络变化日志
  private logNetworkChange(
    oldCapabilities: connection.NetCapabilities | null,
    newCapabilities: connection.NetCapabilities,
    changeType: string
  ): void {
    const oldInfo = oldCapabilities ? this.formatCapabilities(oldCapabilities) : '无';
    const newInfo = this.formatCapabilities(newCapabilities);
    
    console.info(`网络变化记录:
      变化类型: ${changeType}
      之前: ${oldInfo}
      现在: ${newInfo}
      时间: ${new Date().toISOString()}
    `);
  }
  
  // 格式化网络能力信息
  private formatCapabilities(capabilities: connection.NetCapabilities): string {
    if (!capabilities) {
      return '无网络能力';
    }
    
    const bearerTypes = capabilities.bearerTypes.map(type => {
      switch (type) {
        case connection.NetBearType.BEARER_WIFI:
          return 'Wi-Fi';
        case connection.NetBearType.BEARER_CELLULAR:
          return '蜂窝网络';
        case connection.NetBearType.BEARER_ETHERNET:
          return '以太网';
        case connection.NetBearType.BEARER_BLUETOOTH:
          return '蓝牙';
        case connection.NetBearType.BEARER_VPN:
          return 'VPN';
        case connection.NetBearType.BEARER_WIFI_AWARE:
          return 'Wi-Fi Aware';
        case connection.NetBearType.BEARER_LOWPAN:
          return 'LoWPAN';
        default:
          return `未知(${type})`;
      }
    }).join(', ');
    
    const netCaps = capabilities.netCapabilities.map(cap => {
      switch (cap) {
        case connection.NetCap.NET_CAPABILITY_INTERNET:
          return '可访问互联网';
        case connection.NetCap.NET_CAPABILITY_NOT_METERED:
          return '不计费';
        case connection.NetCap.NET_CAPABILITY_NOT_ROAMING:
          return '非漫游';
        case connection.NetCap.NET_CAPABILITY_VALIDATED:
          return '已验证';
        case connection.NetCap.NET_CAPABILITY_NOT_CONGESTED:
          return '不拥塞';
        case connection.NetCap.NET_CAPABILITY_NOT_SUSPENDED:
          return '未挂起';
        default:
          return `其他能力(${cap})`;
      }
    }).join(', ');
    
    return `类型: [${bearerTypes}], 能力: [${netCaps}]`;
  }
  
  // 添加网络变化监听器
  addListener(callback: NetworkChangeCallback): void {
    if (!this.listeners.includes(callback)) {
      this.listeners.push(callback);
      console.info('网络变化监听器已添加');
    }
  }
  
  // 移除网络变化监听器
  removeListener(callback: NetworkChangeCallback): void {
    const index = this.listeners.indexOf(callback);
    if (index !== -1) {
      this.listeners.splice(index, 1);
      console.info('网络变化监听器已移除');
    }
  }
  
  // 获取当前网络类型
  getCurrentNetworkType(): string {
    if (!this.currentNetCapabilities) {
      return NetworkMonitor.NetworkType.UNKNOWN;
    }
    
    const bearerTypes = this.currentNetCapabilities.bearerTypes;
    
    if (bearerTypes.includes(connection.NetBearType.BEARER_WIFI)) {
      return NetworkMonitor.NetworkType.WIFI;
    }
    
    if (bearerTypes.includes(connection.NetBearType.BEARER_CELLULAR)) {
      return NetworkMonitor.NetworkType.CELLULAR;
    }
    
    if (bearerTypes.includes(connection.NetBearType.BEARER_ETHERNET)) {
      return NetworkMonitor.NetworkType.ETHERNET;
    }
    
    return NetworkMonitor.NetworkType.UNKNOWN;
  }
  
  // 检查是否计费网络
  isMeteredNetwork(): boolean {
    if (!this.currentNetCapabilities) {
      return true; // 默认按计费网络处理
    }
    
    // NOT_METERED表示不计费,所以如果包含这个能力,就是不计费网络
    const hasNotMetered = this.currentNetCapabilities.netCapabilities.includes(
      connection.NetCap.NET_CAPABILITY_NOT_METERED
    );
    
    return !hasNotMetered;
  }
  
  // 检查是否漫游状态
  isRoaming(): boolean {
    if (!this.currentNetCapabilities) {
      return false; // 默认按非漫游处理
    }
    
    // NOT_ROAMING表示非漫游,所以如果不包含这个能力,就是漫游状态
    const hasNotRoaming = this.currentNetCapabilities.netCapabilities.includes(
      connection.NetCap.NET_CAPABILITY_NOT_ROAMING
    );
    
    return !hasNotRoaming;
  }
  
  // 检查网络是否可用
  isNetworkAvailable(): boolean {
    if (!this.currentNetCapabilities) {
      return false;
    }
    
    // 检查是否有INTERNET能力
    const hasInternet = this.currentNetCapabilities.netCapabilities.includes(
      connection.NetCap.NET_CAPABILITY_INTERNET
    );
    
    // 检查是否有VALIDATED能力(网络已验证)
    const hasValidated = this.currentNetCapabilities.netCapabilities.includes(
      connection.NetCap.NET_CAPABILITY_VALIDATED
    );
    
    return hasInternet && hasValidated;
  }
  
  // 获取网络能力详情
  getNetworkDetails(): NetworkDetails {
    if (!this.currentNetCapabilities) {
      return {
        type: NetworkMonitor.NetworkType.UNKNOWN,
        isMetered: true,
        isRoaming: false,
        isAvailable: false,
        bearerTypes: [],
        capabilities: []
      };
    }
    
    return {
      type: this.getCurrentNetworkType(),
      isMetered: this.isMeteredNetwork(),
      isRoaming: this.isRoaming(),
      isAvailable: this.isNetworkAvailable(),
      bearerTypes: this.currentCapabilities.bearerTypes,
      capabilities: this.currentCapabilities.netCapabilities
    };
  }
  
  // 清理资源
  cleanup(): void {
    if (this.netHandle) {
      // 移除所有监听器
      this.netHandle.off('netCapabilitiesChange');
      this.netHandle.off('connectionStateChange');
      
      // 销毁网络连接实例
      connection.destroyNetConnection(this.netHandle);
      this.netHandle = null;
    }
    
    // 清空监听器列表
    this.listeners = [];
    this.currentNetCapabilities = null;
    
    console.info('网络监听器资源已清理');
  }
}

// 网络详情接口
interface NetworkDetails {
  type: string;
  isMetered: boolean;
  isRoaming: boolean;
  isAvailable: boolean;
  bearerTypes: number[];
  capabilities: number[];
}

3.3 步骤二:智能网络策略管理器

基于网络状态,智能调整应用行为,如视频清晰度、预加载策略等。

复制代码
// NetworkStrategyManager.ets - 智能网络策略管理器
import promptAction from '@ohos.promptAction';
import { NetworkMonitor } from './NetworkMonitor';

export class NetworkStrategyManager {
  private static instance: NetworkStrategyManager;
  private networkMonitor: NetworkMonitor;
  private currentStrategy: NetworkStrategy = NetworkStrategy.NORMAL;
  private userPreferences: UserPreferences;
  
  // 网络策略枚举
  static NetworkStrategy = {
    ULTRA_SAVE: 'ultra_save',     // 超省流模式
    SAVE: 'save',                 // 省流模式
    NORMAL: 'normal',             // 普通模式
    HIGH_QUALITY: 'high_quality', // 高质量模式
    ULTRA_QUALITY: 'ultra_quality' // 超高质量模式
  };
  
  // 用户偏好接口
  interface UserPreferences {
    autoSwitchStrategy: boolean;      // 是否自动切换策略
    notifyOnNetworkChange: boolean;   // 网络变化时是否通知
    allowCellularForVideo: boolean;   // 是否允许移动网络播放视频
    cellularVideoQuality: string;     // 移动网络视频质量
    wifiVideoQuality: string;         // Wi-Fi视频质量
    preloadOnWifiOnly: boolean;       // 仅Wi-Fi预加载
  }
  
  // 默认用户偏好
  private defaultPreferences: UserPreferences = {
    autoSwitchStrategy: true,
    notifyOnNetworkChange: true,
    allowCellularForVideo: true,
    cellularVideoQuality: '480p',
    wifiVideoQuality: '1080p',
    preloadOnWifiOnly: true
  };
  
  private constructor() {
    this.networkMonitor = NetworkMonitor.getInstance();
    this.userPreferences = { ...this.defaultPreferences };
    this.setupNetworkListener();
  }
  
  static getInstance(): NetworkStrategyManager {
    if (!NetworkStrategyManager.instance) {
      NetworkStrategyManager.instance = new NetworkStrategyManager();
    }
    return NetworkStrategyManager.instance;
  }
  
  // 设置网络监听
  private setupNetworkListener(): void {
    this.networkMonitor.addListener(
      (oldCapabilities, newCapabilities, changeType) => {
        this.handleNetworkChange(oldCapabilities, newCapabilities, changeType);
      }
    );
  }
  
  // 处理网络变化
  private handleNetworkChange(
    oldCapabilities: any,
    newCapabilities: any,
    changeType: string
  ): void {
    console.info(`网络变化处理: ${changeType}`);
    
    // 根据变化类型调整策略
    switch (changeType) {
      case 'WIFI_TO_CELLULAR':
        this.handleWifiToCellular();
        break;
        
      case 'CELLULAR_TO_WIFI':
        this.handleCellularToWifi();
        break;
        
      case 'UNMETERED_TO_METERED':
        this.handleToMetered();
        break;
        
      case 'METERED_TO_UNMETERED':
        this.handleToUnmetered();
        break;
        
      case 'HOME_TO_ROAMING':
        this.handleToRoaming();
        break;
        
      case 'ROAMING_TO_HOME':
        this.handleToHome();
        break;
    }
    
    // 更新当前策略
    this.updateCurrentStrategy();
  }
  
  // Wi-Fi切换到移动网络
  private handleWifiToCellular(): void {
    console.info('网络从Wi-Fi切换到移动数据');
    
    // 显示通知
    if (this.userPreferences.notifyOnNetworkChange) {
      this.showNetworkChangeNotification(
        '网络切换提醒',
        '已从Wi-Fi切换到移动数据,请注意流量使用',
        'warning'
      );
    }
    
    // 检查是否允许移动网络播放视频
    if (!this.userPreferences.allowCellularForVideo) {
      this.pauseVideoPlayback();
    }
    
    // 停止预加载
    if (this.userPreferences.preloadOnWifiOnly) {
      this.stopPreloading();
    }
  }
  
  // 移动网络切换到Wi-Fi
  private handleCellularToWifi(): void {
    console.info('网络从移动数据切换到Wi-Fi');
    
    // 显示通知
    if (this.userPreferences.notifyOnNetworkChange) {
      this.showNetworkChangeNotification(
        '网络切换提醒',
        '已从移动数据切换到Wi-Fi,可以享受更高质量的内容',
        'success'
      );
    }
    
    // 恢复视频播放(如果之前被暂停)
    this.resumeVideoPlayback();
    
    // 开始预加载
    if (this.userPreferences.preloadOnWifiOnly) {
      this.startPreloading();
    }
  }
  
  // 切换到计费网络
  private handleToMetered(): void {
    console.info('切换到计费网络');
    
    if (this.userPreferences.notifyOnNetworkChange) {
      this.showNetworkChangeNotification(
        '计费网络提醒',
        '当前网络可能会计费,请注意流量使用',
        'warning'
      );
    }
    
    // 切换到省流模式
    this.switchToSaveMode();
  }
  
  // 切换到不计费网络
  private handleToUnmetered(): void {
    console.info('切换到不计费网络');
    
    // 切换到高质量模式
    this.switchToHighQualityMode();
  }
  
  // 切换到漫游状态
  private handleToRoaming(): void {
    console.info('切换到漫游状态');
    
    if (this.userPreferences.notifyOnNetworkChange) {
      this.showNetworkChangeNotification(
        '漫游提醒',
        '当前处于漫游状态,请注意额外费用',
        'warning'
      );
    }
    
    // 切换到超省流模式
    this.switchToUltraSaveMode();
  }
  
  // 切换到本地网络
  private handleToHome(): void {
    console.info('切换到本地网络');
    
    // 恢复之前的策略
    this.updateCurrentStrategy();
  }
  
  // 显示网络变化通知
  private showNetworkChangeNotification(
    title: string,
    message: string,
    type: 'info' | 'success' | 'warning' | 'error'
  ): void {
    try {
      promptAction.showToast({
        message: `${title}: ${message}`,
        duration: 3000,
        bottom: 200
      });
      
      // 记录通知
      console.info(`网络变化通知: ${title} - ${message}`);
      
    } catch (err) {
      console.error('显示通知失败:', err);
    }
  }
  
  // 暂停视频播放
  private pauseVideoPlayback(): void {
    console.info('暂停视频播放(移动网络限制)');
    // 实际开发中调用视频播放器的暂停方法
    // videoPlayer.pause();
  }
  
  // 恢复视频播放
  private resumeVideoPlayback(): void {
    console.info('恢复视频播放(切换到Wi-Fi)');
    // 实际开发中调用视频播放器的恢复方法
    // videoPlayer.resume();
  }
  
  // 停止预加载
  private stopPreloading(): void {
    console.info('停止预加载(移动网络限制)');
    // 实际开发中停止所有预加载任务
    // preloadManager.stopAll();
  }
  
  // 开始预加载
  private startPreloading(): void {
    console.info('开始预加载(切换到Wi-Fi)');
    // 实际开发中开始预加载任务
    // preloadManager.start();
  }
  
  // 切换到省流模式
  private switchToSaveMode(): void {
    console.info('切换到省流模式');
    
    // 调整视频质量
    this.adjustVideoQuality('480p');
    
    // 禁用自动播放
    this.disableAutoplay();
    
    // 减少图片质量
    this.reduceImageQuality();
    
    this.currentStrategy = NetworkStrategyManager.NetworkStrategy.SAVE;
  }
  
  // 切换到超省流模式
  private switchToUltraSaveMode(): void {
    console.info('切换到超省流模式');
    
    // 调整视频质量到最低
    this.adjustVideoQuality('240p');
    
    // 禁用所有媒体自动加载
    this.disableAllMediaAutoload();
    
    // 仅加载文本内容
    this.loadTextOnly();
    
    this.currentStrategy = NetworkStrategyManager.NetworkStrategy.ULTRA_SAVE;
  }
  
  // 切换到高质量模式
  private switchToHighQualityMode(): void {
    console.info('切换到高质量模式');
    
    // 调整视频质量
    this.adjustVideoQuality(this.userPreferences.wifiVideoQuality);
    
    // 启用自动播放
    this.enableAutoplay();
    
    // 提高图片质量
    this.increaseImageQuality();
    
    this.currentStrategy = NetworkStrategyManager.NetworkStrategy.HIGH_QUALITY;
  }
  
  // 调整视频质量
  private adjustVideoQuality(quality: string): void {
    console.info(`调整视频质量到: ${quality}`);
    // 实际开发中调用视频播放器的质量调整方法
    // videoPlayer.setQuality(quality);
  }
  
  // 禁用自动播放
  private disableAutoplay(): void {
    console.info('禁用自动播放');
    // 实际开发中设置自动播放为false
    // autoplayManager.setEnabled(false);
  }
  
  // 启用自动播放
  private enableAutoplay(): void {
    console.info('启用自动播放');
    // 实际开发中设置自动播放为true
    // autoplayManager.setEnabled(true);
  }
  
  // 减少图片质量
  private reduceImageQuality(): void {
    console.info('减少图片质量');
    // 实际开发中设置图片加载质量为低
    // imageLoader.setQuality('low');
  }
  
  // 提高图片质量
  private increaseImageQuality(): void {
    console.info('提高图片质量');
    // 实际开发中设置图片加载质量为高
    // imageLoader.setQuality('high');
  }
  
  // 禁用所有媒体自动加载
  private disableAllMediaAutoload(): void {
    console.info('禁用所有媒体自动加载');
    // 实际开发中禁用所有媒体自动加载
    // mediaLoader.setAutoload(false);
  }
  
  // 仅加载文本内容
  private loadTextOnly(): void {
    console.info('仅加载文本内容');
    // 实际开发中设置仅加载文本
    // contentLoader.setTextOnly(true);
  }
  
  // 更新当前策略
  private updateCurrentStrategy(): void {
    if (!this.userPreferences.autoSwitchStrategy) {
      return;
    }
    
    const networkDetails = this.networkMonitor.getNetworkDetails();
    let newStrategy: string;
    
    if (!networkDetails.isAvailable) {
      newStrategy = NetworkStrategyManager.NetworkStrategy.ULTRA_SAVE;
    } else if (networkDetails.isRoaming) {
      newStrategy = NetworkStrategyManager.NetworkStrategy.ULTRA_SAVE;
    } else if (networkDetails.isMetered) {
      if (networkDetails.type === NetworkMonitor.NetworkType.CELLULAR) {
        newStrategy = NetworkStrategyManager.NetworkStrategy.SAVE;
      } else {
        newStrategy = NetworkStrategyManager.NetworkStrategy.NORMAL;
      }
    } else {
      // 不计费网络
      if (networkDetails.type === NetworkMonitor.NetworkType.WIFI) {
        newStrategy = NetworkStrategyManager.NetworkStrategy.HIGH_QUALITY;
      } else {
        newStrategy = NetworkStrategyManager.NetworkStrategy.NORMAL;
      }
    }
    
    // 如果策略发生变化,应用新策略
    if (newStrategy !== this.currentStrategy) {
      this.applyStrategy(newStrategy);
      this.currentStrategy = newStrategy;
    }
  }
  
  // 应用策略
  private applyStrategy(strategy: string): void {
    console.info(`应用网络策略: ${strategy}`);
    
    switch (strategy) {
      case NetworkStrategyManager.NetworkStrategy.ULTRA_SAVE:
        this.switchToUltraSaveMode();
        break;
        
      case NetworkStrategyManager.NetworkStrategy.SAVE:
        this.switchToSaveMode();
        break;
        
      case NetworkStrategyManager.NetworkStrategy.NORMAL:
        this.switchToNormalMode();
        break;
        
      case NetworkStrategyManager.NetworkStrategy.HIGH_QUALITY:
        this.switchToHighQualityMode();
        break;
        
      case NetworkStrategyManager.NetworkStrategy.ULTRA_QUALITY:
        this.switchToUltraQualityMode();
        break;
    }
  }
  
  // 切换到普通模式
  private switchToNormalMode(): void {
    console.info('切换到普通模式');
    
    // 调整视频质量到标准
    this.adjustVideoQuality('720p');
    
    // 启用自动播放但有限制
    this.enableAutoplayWithLimits();
    
    this.currentStrategy = NetworkStrategyManager.NetworkStrategy.NORMAL;
  }
  
  // 切换到超高质量模式
  private switchToUltraQualityMode(): void {
    console.info('切换到超高质量模式');
    
    // 调整视频质量到最高
    this.adjustVideoQuality('4k');
    
    // 启用所有优化
    this.enableAllOptimizations();
    
    this.currentStrategy = NetworkStrategyManager.NetworkStrategy.ULTRA_QUALITY;
  }
  
  // 启用自动播放但有限制
  private enableAutoplayWithLimits(): void {
    console.info('启用有限制的自动播放');
    // 实际开发中设置自动播放但有限制条件
    // autoplayManager.setEnabledWithLimits(true);
  }
  
  // 启用所有优化
  private enableAllOptimizations(): void {
    console.info('启用所有优化');
    // 实际开发中启用所有性能和质量优化
    // optimizationManager.enableAll();
  }
  
  // 更新用户偏好
  updatePreferences(preferences: Partial<UserPreferences>): void {
    this.userPreferences = { ...this.userPreferences, ...preferences };
    console.info('用户偏好已更新:', this.userPreferences);
    
    // 根据新偏好更新策略
    this.updateCurrentStrategy();
  }
  
  // 获取当前策略
  getCurrentStrategy(): string {
    return this.currentStrategy;
  }
  
  // 获取策略建议
  getStrategySuggestion(): StrategySuggestion {
    const networkDetails = this.networkMonitor.getNetworkDetails();
    
    return {
      recommendedStrategy: this.currentStrategy,
      networkType: networkDetails.type,
      isMetered: networkDetails.isMetered,
      isRoaming: networkDetails.isRoaming,
      isAvailable: networkDetails.isAvailable,
      suggestion: this.generateSuggestionText(networkDetails)
    };
  }
  
  // 生成建议文本
  private generateSuggestionText(details: NetworkDetails): string {
    if (!details.isAvailable) {
      return '网络不可用,建议检查网络连接';
    }
    
    if (details.isRoaming) {
      return '当前处于漫游状态,建议使用超省流模式以避免高额费用';
    }
    
    if (details.isMetered) {
      if (details.type === NetworkMonitor.NetworkType.CELLULAR) {
        return '当前使用移动数据,建议使用省流模式以节省流量';
      } else {
        return '当前网络可能会计费,建议适当控制流量使用';
      }
    }
    
    if (details.type === NetworkMonitor.NetworkType.WIFI) {
      return '当前使用Wi-Fi,可以享受高质量内容';
    }
    
    return '网络状态正常';
  }
  
  // 清理资源
  cleanup(): void {
    this.networkMonitor.removeListener(this.handleNetworkChange.bind(this));
    console.info('网络策略管理器资源已清理');
  }
}

// 策略建议接口
interface StrategySuggestion {
  recommendedStrategy: string;
  networkType: string;
  isMetered: boolean;
  isRoaming: boolean;
  isAvailable: boolean;
  suggestion: string;
}

3.4 步骤三:集成到实际应用中

将智能网络感知集成到实际的应用中,提供完整的用户体验。

复制代码
// SmartNetworkApp.ets - 智能网络感知应用示例
import { NetworkMonitor } from './NetworkMonitor';
import { NetworkStrategyManager } from './NetworkStrategyManager';

@Entry
@Component
struct SmartNetworkApp {
  @State currentNetworkType: string = '未知';
  @State isMetered: boolean = false;
  @State isRoaming: boolean = false;
  @State currentStrategy: string = 'normal';
  @State networkSuggestion: string = '';
  
  private networkMonitor: NetworkMonitor = NetworkMonitor.getInstance();
  private strategyManager: NetworkStrategyManager = NetworkStrategyManager.getInstance();
  
  aboutToAppear() {
    // 初始化网络监听
    this.initializeNetworkMonitoring();
    
    // 初始化网络策略管理器
    this.initializeStrategyManager();
  }
  
  async initializeNetworkMonitoring() {
    const success = await this.networkMonitor.initialize();
    if (success) {
      // 添加网络变化监听
      this.networkMonitor.addListener(this.handleNetworkChange.bind(this));
      
      // 获取初始网络状态
      this.updateNetworkStatus();
    } else {
      console.error('网络监听初始化失败');
    }
  }
  
  initializeStrategyManager() {
    // 策略管理器会自动初始化
    // 获取当前策略
    this.currentStrategy = this.strategyManager.getCurrentStrategy();
    
    // 获取策略建议
    const suggestion = this.strategyManager.getStrategySuggestion();
    this.networkSuggestion = suggestion.suggestion;
  }
  
  handleNetworkChange(oldCapabilities: any, newCapabilities: any, changeType: string) {
    console.info(`网络变化: ${changeType}`);
    
    // 更新UI状态
    this.updateNetworkStatus();
    
    // 更新策略建议
    const suggestion = this.strategyManager.getStrategySuggestion();
    this.currentStrategy = suggestion.recommendedStrategy;
    this.networkSuggestion = suggestion.suggestion;
    
    // 显示变化提示
    this.showNetworkChangeToast(changeType);
  }
  
  updateNetworkStatus() {
    const details = this.networkMonitor.getNetworkDetails();
    this.currentNetworkType = details.type;
    this.isMetered = details.isMetered;
    this.isRoaming = details.isRoaming;
  }
  
  showNetworkChangeToast(changeType: string) {
    let message = '';
    
    switch (changeType) {
      case 'WIFI_TO_CELLULAR':
        message = '已切换到移动数据,请注意流量使用';
        break;
      case 'CELLULAR_TO_WIFI':
        message = '已切换到Wi-Fi,可以享受更高质量的内容';
        break;
      case 'UNMETERED_TO_METERED':
        message = '当前网络可能会计费,请注意流量使用';
        break;
      case 'HOME_TO_ROAMING':
        message = '当前处于漫游状态,请注意额外费用';
        break;
    }
    
    if (message) {
      promptAction.showToast({
        message: message,
        duration: 3000,
        bottom: 200
      });
    }
  }
  
  getNetworkTypeColor(): ResourceColor {
    switch (this.currentNetworkType) {
      case 'wifi': return '#52C41A';
      case 'cellular': return '#1890FF';
      case 'ethernet': return '#722ED1';
      default: return '#888888';
    }
  }
  
  getStrategyDisplayName(): string {
    const strategyNames = {
      'ultra_save': '超省流模式',
      'save': '省流模式',
      'normal': '普通模式',
      'high_quality': '高质量模式',
      'ultra_quality': '超高质量模式'
    };
    return strategyNames[this.currentStrategy] || '未知模式';
  }
  
  getStrategyColor(): ResourceColor {
    switch (this.currentStrategy) {
      case 'ultra_save': return '#FF4D4F';
      case 'save': return '#FAAD14';
      case 'normal': return '#1890FF';
      case 'high_quality': return '#52C41A';
      case 'ultra_quality': return '#722ED1';
      default: return '#888888';
    }
  }
  
  @Builder
  buildStrategyDescription() {
    Column({ space: 8 }) {
      Row({ space: 10 }) {
        Circle({ width: 12, height: 12 })
          .fill('#FF4D4F')
        
        Text('超省流模式')
          .fontSize(14)
          .fontColor('#333333')
        
        Text(' - 仅加载文本,禁用所有媒体,适合漫游或网络极差时')
          .fontSize(12)
          .fontColor('#666666')
      }
      .width('100%')
      
      Row({ space: 10 }) {
        Circle({ width: 12, height: 12 })
          .fill('#FAAD14')
        
        Text('省流模式')
          .fontSize(14)
          .fontColor('#333333')
        
        Text(' - 低质量图片,禁用自动播放,适合移动数据网络')
          .fontSize(12)
          .fontColor('#666666')
      }
      .width('100%')
      
      Row({ space: 10 }) {
        Circle({ width: 12, height: 12 })
          .fill('#1890FF')
        
        Text('普通模式')
          .fontSize(14)
          .fontColor('#333333')
        
        Text(' - 标准清晰度,有限自动播放,适合普通计费网络')
          .fontSize(12)
          .fontColor('#666666')
      }
      .width('100%')
      
      Row({ space: 10 }) {
        Circle({ width: 12, height: 12 })
          .fill('#52C41A')
        
        Text('高质量模式')
          .fontSize(14)
          .fontColor('#333333')
        
        Text(' - 高清内容,自动播放,适合Wi-Fi不计费网络')
          .fontSize(12)
          .fontColor('#666666')
      }
      .width('100%')
      
      Row({ space: 10 }) {
        Circle({ width: 12, height: 12 })
          .fill('#722ED1')
        
        Text('超高质量模式')
          .fontSize(14)
          .fontColor('#333333')
        
        Text(' - 最高质量,所有优化,适合高速稳定网络')
          .fontSize(12)
          .fontColor('#666666')
      }
      .width('100%')
    }
  }
  
  build() {
    Column({ space: 20 }) {
      // 应用标题
      Text('智能网络感知演示')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .fontColor('#1890FF')
        .margin({ top: 40 })
      
      // 网络状态卡片
      Column({ space: 10 }) {
        Text('当前网络状态')
          .fontSize(18)
          .fontWeight(FontWeight.Medium)
          .fontColor('#333333')
        
        Row({ space: 20 }) {
          Column({ space: 5 }) {
            Text('网络类型')
              .fontSize(14)
              .fontColor('#666666')
            Text(this.currentNetworkType)
              .fontSize(16)
              .fontColor(this.getNetworkTypeColor())
          }
          
          Column({ space: 5 }) {
            Text('计费状态')
              .fontSize(14)
              .fontColor('#666666')
            Text(this.isMetered ? '计费网络' : '不计费网络')
              .fontSize(16)
              .fontColor(this.isMetered ? '#FF4D4F' : '#52C41A')
          }
          
          Column({ space: 5 }) {
            Text('漫游状态')
              .fontSize(14)
              .fontColor('#666666')
            Text(this.isRoaming ? '漫游中' : '本地网络')
              .fontSize(16)
              .fontColor(this.isRoaming ? '#FAAD14' : '#1890FF')
          }
        }
        .width('100%')
        .justifyContent(FlexAlign.SpaceAround)
      }
      .padding(20)
      .backgroundColor('#FFFFFF')
      .borderRadius(12)
      .width('90%')
      .shadow({ radius: 8, color: '#00000010', offsetX: 0, offsetY: 2 })
      
      // 当前策略卡片
      Column({ space: 10 }) {
        Text('当前网络策略')
          .fontSize(18)
          .fontWeight(FontWeight.Medium)
          .fontColor('#333333')
        
        Text(this.getStrategyDisplayName())
          .fontSize(20)
          .fontColor(this.getStrategyColor())
          .margin({ top: 5 })
        
        Text(this.networkSuggestion)
          .fontSize(14)
          .fontColor('#666666')
          .margin({ top: 10 })
          .textAlign(TextAlign.Center)
          .maxLines(3)
      }
      .padding(20)
      .backgroundColor('#FFFFFF')
      .borderRadius(12)
      .width('90%')
      .shadow({ radius: 8, color: '#00000010', offsetX: 0, offsetY: 2 })
      
      // 策略说明
      Column({ space: 10 }) {
        Text('策略说明')
          .fontSize(16)
          .fontWeight(FontWeight.Medium)
          .fontColor('#333333')
        
        this.buildStrategyDescription()
      }
      .padding(20)
      .backgroundColor('#FFFFFF')
      .borderRadius(12)
      .width('90%')
      .shadow({ radius: 8, color: '#00000010', offsetX: 0, offsetY: 2 })
      
      // 操作按钮
      Row({ space: 20 }) {
        Button('手动刷新')
          .width(120)
          .backgroundColor('#1890FF')
          .onClick(() => {
            this.updateNetworkStatus();
            const suggestion = this.strategyManager.getStrategySuggestion();
            this.currentStrategy = suggestion.recommendedStrategy;
            this.networkSuggestion = suggestion.suggestion;
          })
        
        Button('模拟网络切换')
          .width(120)
          .backgroundColor('#52C41A')
          .onClick(() => {
            this.simulateNetworkChange();
          })
      }
      .margin({ top: 20 })
      
      // 使用说明
      Column({ space: 8 }) {
        Text('使用说明')
          .fontSize(16)
          .fontWeight(FontWeight.Medium)
          .fontColor('#333333')
        
        Text('1. 应用会自动监听网络变化并调整策略')
          .fontSize(12)
          .fontColor('#666666')
        
        Text('2. 从Wi-Fi切换到移动数据时会弹出提示')
          .fontSize(12)
          .fontColor('#666666')
        
        Text('3. 在设置中可以自定义网络策略')
          .fontSize(12)
          .fontColor('#666666')
      }
      .padding(20)
      .backgroundColor('#F6FFED')
      .borderRadius(12)
      .width('90%')
      .margin({ top: 20 })
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F5F5')
  }
  
  // 模拟网络变化
  simulateNetworkChange() {
    // 这里应该调用系统API模拟网络变化
    // 由于安全限制,实际应用中无法模拟网络变化
    // 这里只是展示可能的调用方式
    promptAction.showToast({
      message: '模拟网络切换(实际开发中需要系统权限)',
      duration: 2000
    });
  }
}

四、高级功能扩展

4.1 网络质量监控

除了网络类型变化,还可以监控网络质量变化,如信号强度、延迟、带宽等,提供更智能的决策依据。

复制代码
// NetworkQualityMonitor.ets - 网络质量监控器
import connection from '@kit.NetConnectionKit';

export class NetworkQualityMonitor {
  private netHandle: connection.NetConnection;
  private qualityListeners: QualityChangeCallback[] = [];
  private currentQuality: NetworkQuality = {
    level: 'UNKNOWN',
    signalStrength: 0,
    latency: 0,
    bandwidth: 0
  };
  
  // 网络质量等级
  static QualityLevel = {
    EXCELLENT: 'excellent',     // 优秀
    GOOD: 'good',               // 良好
    FAIR: 'fair',               // 一般
    POOR: 'poor',               // 差
    UNKNOWN: 'unknown'         // 未知
  };
  
  // 初始化质量监控
  async initialize(): Promise<boolean> {
    try {
      this.netHandle = connection.createNetConnection();
      
      // 监听网络质量变化
      this.setupQualityListener();
      
      // 获取初始质量
      await this.updateQuality();
      
      return true;
    } catch (err) {
      console.error('网络质量监控初始化失败:', err);
      return false;
    }
  }
  
  // 设置质量监听
  private setupQualityListener(): void {
    // 注意:HarmonyOS API文档中可能没有直接的质量变化监听
    // 这里我们可以通过定时检测来模拟
    setInterval(() => {
      this.updateQuality();
    }, 5000); // 每5秒检测一次
  }
  
  // 更新网络质量
  private async updateQuality(): Promise<void> {
    try {
      const newQuality = await this.measureNetworkQuality();
      const oldQuality = this.currentQuality;
      this.currentQuality = newQuality;
      
      // 如果质量变化超过阈值,通知监听器
      if (this.isQualityChanged(oldQuality, newQuality)) {
        this.notifyQualityChange(oldQuality, newQuality);
      }
    } catch (err) {
      console.error('更新网络质量失败:', err);
    }
  }
  
  // 测量网络质量
  private async measureNetworkQuality(): Promise<NetworkQuality> {
    // 这里可以集成更复杂的质量测量逻辑
    // 例如:测速、ping延迟测试等
    
    return {
      level: this.calculateQualityLevel(),
      signalStrength: await this.getSignalStrength(),
      latency: await this.measureLatency(),
      bandwidth: await this.measureBandwidth()
    };
  }
  
  // 计算质量等级
  private calculateQualityLevel(): string {
    // 根据信号强度、延迟、带宽综合计算
    // 这里简化处理
    if (this.currentQuality.signalStrength > 80) {
      return NetworkQualityMonitor.QualityLevel.EXCELLENT;
    } else if (this.currentQuality.signalStrength > 60) {
      return NetworkQualityMonitor.QualityLevel.GOOD;
    } else if (this.currentQuality.signalStrength > 40) {
      return NetworkQualityMonitor.QualityLevel.FAIR;
    } else {
      return NetworkQualityMonitor.QualityLevel.POOR;
    }
  }
  
  // 获取信号强度
  private async getSignalStrength(): Promise<number> {
    // 实际开发中需要调用系统API获取信号强度
    return 75; // 模拟值
  }
  
  // 测量延迟
  private async measureLatency(): Promise<number> {
    // 实现ping逻辑测量延迟
    return 50; // 模拟50ms延迟
  }
  
  // 测量带宽
  private async measureBandwidth(): Promise<number> {
    // 实现测速逻辑
    return 1024; // 模拟1Mbps带宽
  }
  
  // 检查质量是否变化
  private isQualityChanged(oldQuality: NetworkQuality, newQuality: NetworkQuality): boolean {
    return oldQuality.level !== newQuality.level ||
           Math.abs(oldQuality.signalStrength - newQuality.signalStrength) > 10 ||
           Math.abs(oldQuality.latency - newQuality.latency) > 20 ||
           Math.abs(oldQuality.bandwidth - newQuality.bandwidth) > 100;
  }
  
  // 通知质量变化
  private notifyQualityChange(oldQuality: NetworkQuality, newQuality: NetworkQuality): void {
    this.qualityListeners.forEach(listener => {
      listener(oldQuality, newQuality);
    });
  }
  
  // 添加质量监听器
  addQualityListener(callback: QualityChangeCallback): void {
    this.qualityListeners.push(callback);
  }
  
  // 获取当前质量
  getCurrentQuality(): NetworkQuality {
    return { ...this.currentQuality };
  }
}

// 网络质量接口
interface NetworkQuality {
  level: string;
  signalStrength: number; // 0-100
  latency: number; // ms
  bandwidth: number; // kbps
}

type QualityChangeCallback = (
  oldQuality: NetworkQuality,
  newQuality: NetworkQuality
) => void;

4.2 网络使用统计

记录应用在不同网络类型下的数据使用情况,帮助用户了解流量消耗。

复制代码
// NetworkUsageTracker.ets - 网络使用统计
export class NetworkUsageTracker {
  private usageData: Map<string, NetworkUsageRecord> = new Map();
  private currentSession: NetworkUsageRecord | null = null;
  
  // 开始会话
  startSession(networkType: string): void {
    this.currentSession = {
      networkType,
      startTime: Date.now(),
      dataUsed: 0,
      duration: 0
    };
    
    console.info(`开始网络使用会话: ${networkType}`);
  }
  
  // 记录数据使用
  recordDataUsage(bytes: number): void {
    if (!this.currentSession) {
      console.warn('没有活动的会话,忽略数据使用记录');
      return;
    }
    
    this.currentSession.dataUsed += bytes;
    
    // 更新总量统计
    const key = this.currentSession.networkType;
    if (!this.usageData.has(key)) {
      this.usageData.set(key, {
        networkType: key,
        totalDataUsed: 0,
        sessionCount: 0,
        totalDuration: 0
      });
    }
    
    const totalRecord = this.usageData.get(key)!;
    totalRecord.totalDataUsed += bytes;
  }
  
  // 结束会话
  endSession(): void {
    if (!this.currentSession) {
      return;
    }
    
    const endTime = Date.now();
    this.currentSession.duration = endTime - this.currentSession.startTime;
    
    // 更新总量统计
    const key = this.currentSession.networkType;
    if (this.usageData.has(key)) {
      const totalRecord = this.usageData.get(key)!;
      totalRecord.sessionCount++;
      totalRecord.totalDuration += this.currentSession.duration;
    }
    
    console.info(`结束网络使用会话: 
      网络类型: ${this.currentSession.networkType}
      使用数据: ${this.formatBytes(this.currentSession.dataUsed)}
      持续时间: ${this.formatDuration(this.currentSession.duration)}
    `);
    
    this.currentSession = null;
  }
  
  // 获取统计摘要
  getSummary(): NetworkUsageSummary {
    let totalData = 0;
    let totalSessions = 0;
    let totalDuration = 0;
    
    this.usageData.forEach(record => {
      totalData += record.totalDataUsed;
      totalSessions += record.sessionCount;
      totalDuration += record.totalDuration;
    });
    
    return {
      totalDataUsed: totalData,
      totalSessions,
      totalDuration,
      byNetworkType: Array.from(this.usageData.entries()).map(([type, record]) => ({
        networkType: type,
        dataUsed: record.totalDataUsed,
        dataUsedFormatted: this.formatBytes(record.totalDataUsed),
        sessionCount: record.sessionCount,
        duration: record.totalDuration,
        durationFormatted: this.formatDuration(record.totalDuration)
      }))
    };
  }
  
  // 格式化字节
  private formatBytes(bytes: number): string {
    if (bytes < 1024) {
      return `${bytes} B`;
    } else if (bytes < 1024 * 1024) {
      return `${(bytes / 1024).toFixed(2)} KB`;
    } else if (bytes < 1024 * 1024 * 1024) {
      return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
    } else {
      return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
    }
  }
  
  // 格式化持续时间
  private formatDuration(ms: number): string {
    const seconds = Math.floor(ms / 1000);
    const minutes = Math.floor(seconds / 60);
    const hours = Math.floor(minutes / 60);
    
    if (hours > 0) {
      return `${hours}h ${minutes % 60}m`;
    } else if (minutes > 0) {
      return `${minutes}m ${seconds % 60}s`;
    } else {
      return `${seconds}s`;
    }
  }
  
  // 生成使用报告
  generateReport(): NetworkUsageReport {
    const summary = this.getSummary();
    
    return {
      timestamp: Date.now(),
      summary,
      recommendations: this.generateRecommendations(summary)
    };
  }
  
  // 生成建议
  private generateRecommendations(summary: NetworkUsageSummary): string[] {
    const recommendations: string[] = [];
    
    // 检查移动数据使用情况
    const cellularData = summary.byNetworkType.find(item => item.networkType === 'cellular');
    if (cellularData && cellularData.dataUsed > 100 * 1024 * 1024) { // 超过100MB
      recommendations.push('移动数据使用较多,建议在Wi-Fi环境下下载大文件');
    }
    
    // 检查漫游使用
    const roamingData = summary.byNetworkType.find(item => item.networkType === 'cellular_roaming');
    if (roamingData && roamingData.dataUsed > 10 * 1024 * 1024) { // 超过10MB
      recommendations.push('漫游状态下使用较多数据,请注意额外费用');
    }
    
    return recommendations;
  }
}

// 网络使用记录接口
interface NetworkUsageRecord {
  networkType: string;
  dataUsed: number; // 字节
  startTime: number; // 时间戳
  duration: number; // 毫秒
}

// 网络使用统计接口
interface NetworkUsageStats {
  networkType: string;
  totalDataUsed: number;
  sessionCount: number;
  totalDuration: number;
}

// 统计摘要接口
interface NetworkUsageSummary {
  totalDataUsed: number;
  totalSessions: number;
  totalDuration: number;
  byNetworkType: Array<{
    networkType: string;
    dataUsed: number;
    dataUsedFormatted: string;
    sessionCount: number;
    duration: number;
    durationFormatted: string;
  }>;
}

// 使用报告接口
interface NetworkUsageReport {
  timestamp: number;
  summary: NetworkUsageSummary;
  recommendations: string[];
}

五、最佳实践与优化建议

5.1 性能优化

  1. 延迟监听注册:不要过早注册网络变化监听器,应在页面显示时才注册

  2. 适时取消监听:页面隐藏或组件销毁时及时取消监听

  3. 防抖处理:网络状态可能频繁变化,添加防抖避免过度处理

  4. 后台优化:应用在后台时应适当降低监听频率

5.2 用户体验优化

  1. 渐进式提示:首次切换到移动数据时给予详细提示,后续可简化

  2. 用户可控:提供设置选项让用户控制提示频率和方式

  3. 智能学习:记录用户选择,逐渐减少不必要的提示

  4. 多场景适配:根据不同应用场景调整提示策略

5.3 兼容性考虑

  1. API版本检查:检查系统版本支持情况

  2. 降级方案:在不支持的设备上提供基础功能

  3. 权限处理:优雅处理权限被拒绝的情况

  4. 错误恢复:网络异常时的自动恢复机制

六、总结

通过本文的深入讲解,我们了解了HarmonyOS网络能力监听的完整实现方案。从简单的网络类型检测到复杂的智能策略管理,从基础的状态监听到高级的质量分析,我们构建了一个完整的网络感知系统。

核心价值

  • 避免流量偷跑:及时提示网络变化,保护用户流量

  • 提升用户体验:智能调整应用行为,提供最佳体验

  • 节省用户费用:漫游状态下自动开启省流模式

  • 增强应用可靠性:网络异常时自动降级,保证基本功能

技术要点回顾

  1. 使用getNetCapabilities()获取初始网络状态

  2. 使用on('netCapabilitiesChange')监听网络变化

  3. 根据网络状态智能调整应用策略

  4. 提供用户友好的提示和设置选项

  5. 添加网络使用统计和分析功能

实际应用建议

  • 视频类应用:根据网络质量自动调整清晰度

  • 地图导航应用:离线地图仅在Wi-Fi下下载

  • 社交应用:大文件仅在Wi-Fi下自动下载

  • 新闻应用:移动网络下仅加载文本和缩略图

通过实现智能网络感知,你的应用将变得更加贴心、智能,能够更好地适应各种网络环境,为用户提供始终如一的优秀体验。

相关推荐
niucloud-admin2 小时前
PHP SAAS 框架常见问题——安装插件提示不适配框架版本
php
凌波粒2 小时前
Java 8 “新”特性详解:Lambda、函数式接口、Stream、Optional 与方法引用
java·开发语言·idea
拾贰_C3 小时前
【Google | Gemini | API | POST】怎么使用Google 的Gemini API (原生版)
开发语言·lua
t***5443 小时前
如何在Dev-C++中选择Clang编译器
开发语言·c++
橙子199110163 小时前
Java 基础相关
java·开发语言
星越华夏4 小时前
python——三角函数用法
开发语言·python
代码中介商4 小时前
C语言数据存储深度解析:从原码反码补码到浮点数存储
c语言·开发语言·内存
2501_933329557 小时前
企业级舆情监测系统技术解析:Infoseek数字公关AI中台架构与实践
开发语言·人工智能·自然语言处理·架构