HarmonyOS APP中WiFi连接管理小知识

举报
Jack20 发表于 2026/06/19 20:04:21 2026/06/19
【摘要】 当你的鸿蒙应用需要联网时,WiFi连接管理是绕不开的基础能力。无论是智能家居控制、在线视频播放,还是数据同步,稳定的WiFi连接都是用户体验的基石。今天咱们就来聊聊鸿蒙系统中的WiFi连接管理,看看如何优雅地实现设备配置、连接控制和状态监听。 一、背景与动机 1.1 为什么需要WiFi连接管理?想象一下这样的场景:你开发了一款智能家居控制App,用户需要先连接到家中的智能设备热点进行配网,然...

当你的鸿蒙应用需要联网时,WiFi连接管理是绕不开的基础能力。无论是智能家居控制、在线视频播放,还是数据同步,稳定的WiFi连接都是用户体验的基石。今天咱们就来聊聊鸿蒙系统中的WiFi连接管理,看看如何优雅地实现设备配置、连接控制和状态监听。

一、背景与动机

1.1 为什么需要WiFi连接管理?

想象一下这样的场景:你开发了一款智能家居控制App,用户需要先连接到家中的智能设备热点进行配网,然后设备才能接入家庭WiFi。这个过程就涉及到WiFi的扫描、连接、状态监听等一系列操作。

再比如,一款在线视频应用,当用户从WiFi环境切换到移动数据时,你需要及时感知网络变化,提示用户或自动暂停播放以节省流量。这些都离不开WiFi连接管理能力。

1.2 鸿蒙WiFi管理架构

鸿蒙系统提供了完整的WiFi管理API,主要包含以下几个模块:

模块 功能 关键API
wifiManager WiFi开关控制、连接管理 enableWifi, connect, disconnect
wifiScan WiFi扫描 scan, getScanResults
wifiDevice 设备信息获取 getLinkedInfo, getCurrentSignal
wifiGroup 分组管理 基于场景的WiFi策略

二、核心原理

2.1 WiFi连接流程

WiFi连接看似简单,实则涉及多个步骤:扫描可用网络 → 选择目标网络 → 配置连接参数 → 发起连接 → 等待结果。整个过程需要处理各种异常情况,比如密码错误、信号太弱、路由器限制等。

图片.png

2.2 权限模型

鸿蒙系统的WiFi管理需要申请相应权限,这是安全机制的重要一环:

// module.json5 中配置权限
{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.GET_WIFI_INFO",
        "reason": "获取WiFi信息用于网络状态显示"
      },
      {
        "name": "ohos.permission.SET_WIFI_INFO",
        "reason": "修改WiFi配置用于连接网络"
      },
      {
        "name": "ohos.permission.GET_WIFI_CONFIG",
        "reason": "获取已保存的WiFi配置"
      },
      {
        "name": "ohos.permission.SET_WIFI_CONFIG",
        "reason": "保存WiFi配置信息"
      },
      {
        "name": "ohos.permission.LOCATION",
        "reason": "WiFi扫描需要位置权限"
      }
    ]
  }
}

权限说明

  • GET_WIFI_INFO:获取当前连接的WiFi信息(只读)
  • SET_WIFI_INFO:修改WiFi开关状态、发起连接等(读写)
  • LOCATION:Android/HarmonyOS的安全要求,WiFi扫描涉及位置信息

2.3 WiFi状态机

理解WiFi的状态流转对于正确处理连接逻辑至关重要:
图片.png

三、代码实战

3.1 基础WiFi管理类封装

先来封装一个完整的WiFi管理工具类,涵盖开关控制、扫描、连接等核心功能:

import wifiManager from '@ohos.wifiManager';
import { BusinessError } from '@ohos.base';

/**
 * WiFi管理工具类
 * 封装WiFi开关、扫描、连接等核心功能
 */
export class WifiConnectManager {
  private static instance: WifiConnectManager;
  private scanResultList: Array<wifiManager.WifiScanInfo> = [];
  private connectionStateCallback: ((state: wifiManager.WifiConnState) => void) | null = null;

  private constructor() {
    this.initWifiEventListeners();
  }

  /**
   * 单例模式获取实例
   */
  public static getInstance(): WifiConnectManager {
    if (!WifiConnectManager.instance) {
      WifiConnectManager.instance = new WifiConnectManager();
    }
    return WifiConnectManager.instance;
  }

  /**
   * 初始化WiFi事件监听器
   * 监听连接状态变化、信号强度变化等
   */
  private initWifiEventListeners(): void {
    // 监听WiFi连接状态变化
    wifiManager.on('wifiConnectionChange', (state: wifiManager.WifiConnState) => {
      console.info(`[WiFi] 连接状态变化: ${state}`);
      if (this.connectionStateCallback) {
        this.connectionStateCallback(state);
      }
    });

    // 监听WiFi开关状态变化
    wifiManager.on('wifiStateChange', (state: number) => {
      const stateText = state === 1 ? '已开启' : '已关闭';
      console.info(`[WiFi] 开关状态变化: ${stateText}`);
    });

    // 监听信号强度变化
    wifiManager.on('wifiRssiChange', (rssi: number) => {
      console.info(`[WiFi] 信号强度变化: ${rssi} dBm`);
    });
  }

  /**
   * 检查WiFi是否已开启
   * @returns true-已开启 false-未开启
   */
  public async isWifiEnabled(): Promise<boolean> {
    try {
      const isEnabled = wifiManager.isWifiActive();
      console.info(`[WiFi] 当前状态: ${isEnabled ? '已开启' : '未开启'}`);
      return isEnabled;
    } catch (error) {
      const err = error as BusinessError;
      console.error(`[WiFi] 检查状态失败: ${err.message}`);
      return false;
    }
  }

  /**
   * 开启WiFi
   * 需要SET_WIFI_INFO权限
   */
  public async enableWifi(): Promise<boolean> {
    try {
      const isEnabled = await this.isWifiEnabled();
      if (isEnabled) {
        console.info('[WiFi] WiFi已开启,无需重复操作');
        return true;
      }

      await wifiManager.enableWifi();
      console.info('[WiFi] WiFi开启成功');
      return true;
    } catch (error) {
      const err = error as BusinessError;
      console.error(`[WiFi] 开启失败: ${err.message}`);
      return false;
    }
  }

  /**
   * 关闭WiFi
   */
  public async disableWifi(): Promise<boolean> {
    try {
      await wifiManager.disableWifi();
      console.info('[WiFi] WiFi关闭成功');
      return true;
    } catch (error) {
      const err = error as BusinessError;
      console.error(`[WiFi] 关闭失败: ${err.message}`);
      return false;
    }
  }

  /**
   * 发起WiFi扫描
   * 扫描结果通过getScanResults获取
   */
  public async startScan(): Promise<boolean> {
    try {
      const isEnabled = await this.isWifiEnabled();
      if (!isEnabled) {
        console.error('[WiFi] WiFi未开启,无法扫描');
        return false;
      }

      const scanResult = await wifiManager.scan();
      console.info(`[WiFi] 扫描发起${scanResult ? '成功' : '失败'}`);
      return scanResult;
    } catch (error) {
      const err = error as BusinessError;
      console.error(`[WiFi] 扫描失败: ${err.message}`);
      return false;
    }
  }

  /**
   * 获取扫描结果列表
   * @returns WiFi扫描信息数组
   */
  public async getScanResults(): Promise<Array<wifiManager.WifiScanInfo>> {
    try {
      const results = await wifiManager.getScanResults();
      this.scanResultList = results;
      console.info(`[WiFi] 扫描到 ${results.length} 个网络`);
      return results;
    } catch (error) {
      const err = error as BusinessError;
      console.error(`[WiFi] 获取扫描结果失败: ${err.message}`);
      return [];
    }
  }

  /**
   * 连接到指定WiFi网络
   * @param ssid WiFi名称
   * @param password WiFi密码
   * @param securityType 安全类型
   */
  public async connectToWifi(
    ssid: string,
    password: string,
    securityType: wifiManager.WifiSecurityType = wifiManager.WifiSecurityType.WIFI_SEC_TYPE_PSK
  ): Promise<boolean> {
    try {
      // 构建WiFi配置
      const wifiConfig: wifiManager.WifiDeviceConfig = {
        ssid: ssid,
        preSharedKey: password,
        securityType: securityType,
        isHiddenSsid: false
      };

      // 添加网络配置
      const networkId = await wifiManager.addDeviceConfig(wifiConfig);
      console.info(`[WiFi] 网络配置已添加,ID: ${networkId}`);

      // 连接到指定网络
      await wifiManager.connectToNetwork(networkId);
      console.info(`[WiFi] 正在连接到 ${ssid}...`);
      return true;
    } catch (error) {
      const err = error as BusinessError;
      console.error(`[WiFi] 连接失败: ${err.message}`);
      return false;
    }
  }

  /**
   * 断开当前WiFi连接
   */
  public async disconnect(): Promise<boolean> {
    try {
      await wifiManager.disconnect();
      console.info('[WiFi] 已断开连接');
      return true;
    } catch (error) {
      const err = error as BusinessError;
      console.error(`[WiFi] 断开连接失败: ${err.message}`);
      return false;
    }
  }

  /**
   * 获取当前连接信息
   * @returns 连接信息对象
   */
  public async getLinkedInfo(): Promise<wifiManager.WifiLinkedInfo | null> {
    try {
      const linkedInfo = await wifiManager.getLinkedInfo();
      console.info(`[WiFi] 当前连接: ${linkedInfo.ssid}, 信号: ${linkedInfo.rssi} dBm`);
      return linkedInfo;
    } catch (error) {
      const err = error as BusinessError;
      console.error(`[WiFi] 获取连接信息失败: ${err.message}`);
      return null;
    }
  }

  /**
   * 注册连接状态回调
   * @param callback 状态变化回调函数
   */
  public setConnectionStateCallback(callback: (state: wifiManager.WifiConnState) => void): void {
    this.connectionStateCallback = callback;
  }

  /**
   * 移除所有事件监听
   * 在页面销毁时调用
   */
  public removeAllListeners(): void {
    wifiManager.off('wifiConnectionChange');
    wifiManager.off('wifiStateChange');
    wifiManager.off('wifiRssiChange');
    console.info('[WiFi] 已移除所有监听');
  }
}

3.2 WiFi扫描列表UI实现

接下来实现一个完整的WiFi扫描列表页面,包含扫描、展示、连接等功能:

import { WifiConnectManager } from './WifiConnectManager';
import wifiManager from '@ohos.wifiManager';

@Entry
@Component
struct WifiScanPage {
  // WiFi管理器实例
  private wifiManager: WifiConnectManager = WifiConnectManager.getInstance();
  
  // 状态变量
  @State scanResults: Array<wifiManager.WifiScanInfo> = [];
  @State isScanning: boolean = false;
  @State isConnected: boolean = false;
  @State connectedSsid: string = '';
  @State wifiEnabled: boolean = false;
  
  // 连接对话框状态
  @State showConnectDialog: boolean = false;
  @State selectedWifi: wifiManager.WifiScanInfo | null = null;
  @State inputPassword: string = '';

  aboutToAppear(): void {
    this.checkWifiState();
    this.registerCallbacks();
  }

  aboutToDisappear(): void {
    this.wifiManager.removeAllListeners();
  }

  /**
   * 检查WiFi状态
   */
  async checkWifiState(): Promise<void> {
    this.wifiEnabled = await this.wifiManager.isWifiEnabled();
    if (this.wifiEnabled) {
      const linkedInfo = await this.wifiManager.getLinkedInfo();
      if (linkedInfo) {
        this.isConnected = true;
        this.connectedSsid = linkedInfo.ssid;
      }
    }
  }

  /**
   * 注册状态回调
   */
  registerCallbacks(): void {
    this.wifiManager.setConnectionStateCallback((state: wifiManager.WifiConnState) => {
      if (state === wifiManager.WifiConnState.WIFI_CONNECTED) {
        this.isConnected = true;
        this.refreshConnectedInfo();
      } else if (state === wifiManager.WifiConnState.WIFI_DISCONNECTED) {
        this.isConnected = false;
        this.connectedSsid = '';
      }
    });
  }

  /**
   * 刷新连接信息
   */
  async refreshConnectedInfo(): Promise<void> {
    const linkedInfo = await this.wifiManager.getLinkedInfo();
    if (linkedInfo) {
      this.connectedSsid = linkedInfo.ssid;
    }
  }

  /**
   * 执行WiFi扫描
   */
  async performScan(): Promise<void> {
    this.isScanning = true;
    const scanSuccess = await this.wifiManager.startScan();
    
    if (scanSuccess) {
      // 等待扫描完成(实际项目中应使用回调)
      setTimeout(async () => {
        this.scanResults = await this.wifiManager.getScanResults();
        this.isScanning = false;
      }, 3000);
    } else {
      this.isScanning = false;
    }
  }

  /**
   * 打开WiFi开关
   */
  async enableWifi(): Promise<void> {
    const success = await this.wifiManager.enableWifi();
    if (success) {
      this.wifiEnabled = true;
    }
  }

  /**
   * 连接到选中的WiFi
   */
  async connectToSelectedWifi(): Promise<void> {
    if (!this.selectedWifi || !this.inputPassword) {
      return;
    }

    const success = await this.wifiManager.connectToWifi(
      this.selectedWifi.ssid,
      this.inputPassword
    );

    if (success) {
      this.showConnectDialog = false;
      this.inputPassword = '';
    }
  }

  /**
   * 获取信号强度图标
   */
  getSignalIcon(rssi: number): string {
    if (rssi >= -50) return '📶'; // 优秀
    if (rssi >= -60) return '📶'; // 良好
    if (rssi >= -70) return '📶'; // 一般
    return '📶'; // 较弱
  }

  /**
   * 获取信号强度文本
   */
  getSignalText(rssi: number): string {
    if (rssi >= -50) return '优秀';
    if (rssi >= -60) return '良好';
    if (rssi >= -70) return '一般';
    return '较弱';
  }

  build() {
    Column() {
      // 标题栏
      Row() {
        Text('WiFi设置')
          .fontSize(24)
          .fontWeight(FontWeight.Bold)
          .fontColor('#FFFFFF')
        
        Blank()
        
        Toggle({ type: ToggleType.Switch, isOn: this.wifiEnabled })
          .onChange((isOn: boolean) => {
            if (isOn) {
              this.enableWifi();
            } else {
              this.wifiManager.disableWifi();
              this.wifiEnabled = false;
            }
          })
      }
      .width('100%')
      .padding({ left: 20, right: 20, top: 15, bottom: 15 })
      .backgroundColor('#1A1A2E')

      // 当前连接信息
      if (this.isConnected) {
        Row() {
          Text('已连接')
            .fontSize(14)
            .fontColor('#4CAF50')
          
          Text(this.connectedSsid)
            .fontSize(16)
            .fontColor('#FFFFFF')
            .margin({ left: 10 })
          
          Blank()
          
          Button('断开')
            .fontSize(14)
            .backgroundColor('#FF5722')
            .onClick(() => {
              this.wifiManager.disconnect();
            })
        }
        .width('100%')
        .padding(15)
        .backgroundColor('#16213E')
        .margin({ top: 10 })
      }

      // 扫描按钮
      Button(this.isScanning ? '扫描中...' : '扫描网络')
        .width('90%')
        .height(50)
        .backgroundColor(this.wifiEnabled ? '#4A90E2' : '#666666')
        .enabled(this.wifiEnabled && !this.isScanning)
        .onClick(() => {
          this.performScan();
        })
        .margin({ top: 20 })

      // 扫描结果列表
      if (this.scanResults.length > 0) {
        Text('可用网络')
          .fontSize(16)
          .fontColor('#AAAAAA')
          .width('90%')
          .margin({ top: 20, bottom: 10 })

        List() {
          ForEach(this.scanResults, (wifi: wifiManager.WifiScanInfo) => {
            ListItem() {
              this.WifiListItem(wifi)
            }
          }, (wifi: wifiManager.WifiScanInfo) => wifi.ssid)
        }
        .width('90%')
        .height('50%')
        .divider({ strokeWidth: 1, color: '#333333' })
      }

      // 提示信息
      if (!this.wifiEnabled) {
        Column() {
          Text('WiFi已关闭')
            .fontSize(18)
            .fontColor('#AAAAAA')
          
          Text('请打开WiFi开关以扫描可用网络')
            .fontSize(14)
            .fontColor('#666666')
            .margin({ top: 10 })
        }
        .margin({ top: 100 })
      }
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#0F0F1A')
    .bindSheet($$this.showConnectDialog, this.ConnectSheet(), {
      height: 300,
      backgroundColor: '#1A1A2E',
      dragBar: true
    })
  }

  /**
   * WiFi列表项组件
   */
  @Builder
  WifiListItem(wifi: wifiManager.WifiScanInfo) {
    Row() {
      // 信号图标
      Text(this.getSignalIcon(wifi.rssi))
        .fontSize(28)
      
      // 网络信息
      Column() {
        Text(wifi.ssid)
          .fontSize(16)
          .fontColor('#FFFFFF')
        
        Row() {
          Text(this.getSignalText(wifi.rssi))
            .fontSize(12)
            .fontColor('#AAAAAA')
          
          if (wifi.securityType !== wifiManager.WifiSecurityType.WIFI_SEC_TYPE_OPEN) {
            Text('🔒')
              .fontSize(12)
              .margin({ left: 5 })
          }
        }
        .margin({ top: 5 })
      }
      .alignItems(HorizontalAlign.Start)
      .margin({ left: 15 })
      .layoutWeight(1)
      
      // 连接状态
      if (wifi.ssid === this.connectedSsid) {
        Text('已连接')
          .fontSize(14)
          .fontColor('#4CAF50')
      } else {
        Button('连接')
          .fontSize(14)
          .backgroundColor('#4A90E2')
          .onClick(() => {
            this.selectedWifi = wifi;
            if (wifi.securityType === wifiManager.WifiSecurityType.WIFI_SEC_TYPE_OPEN) {
              // 开放网络直接连接
              this.wifiManager.connectToWifi(wifi.ssid, '');
            } else {
              // 需要密码的网络显示输入框
              this.showConnectDialog = true;
            }
          })
      }
    }
    .width('100%')
    .padding(15)
    .backgroundColor('#16213E')
    .borderRadius(8)
  }

  /**
   * 密码输入弹窗
   */
  @Builder
  ConnectSheet() {
    Column() {
      Text('连接到 ' + (this.selectedWifi?.ssid || ''))
        .fontSize(18)
        .fontColor('#FFFFFF')
        .margin({ bottom: 20 })

      TextInput({ placeholder: '请输入WiFi密码' })
        .width('90%')
        .height(50)
        .type(InputType.Password)
        .backgroundColor('#16213E')
        .fontColor('#FFFFFF')
        .onChange((value: string) => {
          this.inputPassword = value;
        })

      Row() {
        Button('取消')
          .width('40%')
          .backgroundColor('#666666')
          .onClick(() => {
            this.showConnectDialog = false;
            this.inputPassword = '';
          })

        Button('连接')
          .width('40%')
          .backgroundColor('#4A90E2')
          .onClick(() => {
            this.connectToSelectedWifi();
          })
      }
      .width('90%')
      .justifyContent(FlexAlign.SpaceBetween)
      .margin({ top: 20 })
    }
    .width('100%')
    .padding(20)
  }
}

3.3 WiFi智能切换策略

在实际应用中,我们经常需要根据场景智能切换WiFi策略,比如省电模式下降低扫描频率,或者在信号弱时自动切换到移动数据:

import wifiManager from '@ohos.wifiManager';
import connection from '@ohos.net.connection';

/**
 * WiFi智能管理策略
 * 根据场景自动调整WiFi行为
 */
export class WifiSmartStrategy {
  private static instance: WifiSmartStrategy;
  private scanInterval: number = 30000; // 默认30秒扫描一次
  private scanTimer: number = -1;
  private weakSignalThreshold: number = -75; // 弱信号阈值
  private isPowerSaveMode: boolean = false;

  private constructor() {}

  public static getInstance(): WifiSmartStrategy {
    if (!WifiSmartStrategy.instance) {
      WifiSmartStrategy.instance = new WifiSmartStrategy();
    }
    return WifiSmartStrategy.instance;
  }

  /**
   * 启动智能扫描
   * 根据当前状态动态调整扫描频率
   */
  public startSmartScan(): void {
    this.stopSmartScan();
    
    const doScan = async () => {
      try {
        // 检查当前连接状态
        const linkedInfo = await wifiManager.getLinkedInfo();
        
        if (linkedInfo && linkedInfo.connState === wifiManager.WifiConnState.WIFI_CONNECTED) {
          // 已连接,检查信号强度
          if (linkedInfo.rssi < this.weakSignalThreshold) {
            console.warn('[WiFi策略] 信号较弱,建议切换网络');
            this.handleWeakSignal(linkedInfo);
          } else {
            console.info('[WiFi策略] 信号良好,降低扫描频率');
            this.adjustScanInterval(true);
          }
        } else {
          // 未连接,提高扫描频率
          console.info('[WiFi策略] 未连接,提高扫描频率');
          this.adjustScanInterval(false);
          await wifiManager.scan();
        }
      } catch (error) {
        console.error('[WiFi策略] 扫描异常:', error);
      }
    };

    // 立即执行一次
    doScan();

    // 设置定时扫描
    this.scanTimer = setInterval(doScan, this.scanInterval);
  }

  /**
   * 停止智能扫描
   */
  public stopSmartScan(): void {
    if (this.scanTimer !== -1) {
      clearInterval(this.scanTimer);
      this.scanTimer = -1;
    }
  }

  /**
   * 调整扫描间隔
   * @param isGoodSignal 信号是否良好
   */
  private adjustScanInterval(isGoodSignal: boolean): void {
    if (this.isPowerSaveMode) {
      // 省电模式:大幅降低扫描频率
      this.scanInterval = 120000; // 2分钟
    } else if (isGoodSignal) {
      // 信号良好:适度降低频率
      this.scanInterval = 60000; // 1分钟
    } else {
      // 信号差或未连接:提高频率
      this.scanInterval = 15000; // 15秒
    }

    // 重启定时器
    this.startSmartScan();
  }

  /**
   * 处理弱信号情况
   * 可触发网络切换提示或自动切换
   */
  private async handleWeakSignal(linkedInfo: wifiManager.WifiLinkedInfo): Promise<void> {
    // 发送弱信号通知
    console.warn(`[WiFi策略] 当前信号: ${linkedInfo.rssi} dBm,低于阈值 ${this.weakSignalThreshold} dBm`);
    
    // 可选:检查是否有更好的网络
    const scanResults = await wifiManager.getScanResults();
    const currentSsid = linkedInfo.ssid;
    
    // 寻找信号更好的同网络AP
    const betterAp = scanResults.find(wifi => 
      wifi.ssid === currentSsid && wifi.rssi > linkedInfo.rssi + 10
    );
    
    if (betterAp) {
      console.info('[WiFi策略] 发现信号更好的同网络AP');
    }
  }

  /**
   * 设置省电模式
   * @param enabled 是否启用
   */
  public setPowerSaveMode(enabled: boolean): void {
    this.isPowerSaveMode = enabled;
    this.adjustScanInterval(true);
    console.info(`[WiFi策略] 省电模式: ${enabled ? '开启' : '关闭'}`);
  }

  /**
   * 检查网络质量
   * 返回综合评分
   */
  public async checkNetworkQuality(): Promise<number> {
    try {
      const linkedInfo = await wifiManager.getLinkedInfo();
      if (!linkedInfo || linkedInfo.connState !== wifiManager.WifiConnState.WIFI_CONNECTED) {
        return 0;
      }

      // 信号强度评分 (0-40分)
      const signalScore = Math.min(40, Math.max(0, (linkedInfo.rssi + 100) * 0.8));

      // 网络延迟评分 (需要实际测量)
      const latencyScore = 30; // 假设值

      // 稳定性评分 (根据历史断连次数)
      const stabilityScore = 30; // 假设值

      return signalScore + latencyScore + stabilityScore;
    } catch (error) {
      return 0;
    }
  }

  /**
   * 获取网络切换建议
   */
  public async getSwitchSuggestion(): Promise<string> {
    const quality = await this.checkNetworkQuality();
    
    if (quality >= 80) {
      return '当前网络质量优秀,无需切换';
    } else if (quality >= 60) {
      return '当前网络质量良好';
    } else if (quality >= 40) {
      return '当前网络质量一般,建议关注';
    } else {
      return '当前网络质量较差,建议切换网络';
    }
  }
}

四、踩坑与注意事项

4.1 权限问题

坑点:WiFi扫描需要位置权限,很多开发者容易遗漏。

// ❌ 错误:只申请WiFi权限
{
  "requestPermissions": [
    { "name": "ohos.permission.GET_WIFI_INFO" }
  ]
}

// ✅ 正确:同时申请位置权限
{
  "requestPermissions": [
    { "name": "ohos.permission.GET_WIFI_INFO" },
    { "name": "ohos.permission.LOCATION" }  // 必须添加
  ]
}

原因:WiFi扫描结果可能包含精确的位置信息(通过WiFi定位技术),出于隐私保护,系统要求必须申请位置权限。

4.2 扫描频率限制

坑点:频繁调用scan()会被系统限制。

// ❌ 错误:高频扫描
setInterval(() => {
  wifiManager.scan();  // 系统会限制,实际扫描间隔远大于预期
}, 1000);

// ✅ 正确:合理间隔
setInterval(() => {
  wifiManager.scan();
}, 30000);  // 建议30秒以上

建议

  • 前台场景:15-30秒扫描一次
  • 后台场景:60-120秒扫描一次
  • 省电模式:120秒以上

4.3 连接超时处理

坑点:connectToNetwork没有超时机制,可能一直等待。

/**
 * 带超时的WiFi连接
 */
async function connectWithTimeout(
  networkId: number,
  timeout: number = 30000
): Promise<boolean> {
  return new Promise((resolve) => {
    let isResolved = false;
    
    // 设置超时
    const timer = setTimeout(() => {
      if (!isResolved) {
        isResolved = true;
        resolve(false);
        console.warn('[WiFi] 连接超时');
      }
    }, timeout);

    // 监听连接结果
    wifiManager.on('wifiConnectionChange', (state: wifiManager.WifiConnState) => {
      if (isResolved) return;
      
      if (state === wifiManager.WifiConnState.WIFI_CONNECTED) {
        isResolved = true;
        clearTimeout(timer);
        resolve(true);
      } else if (state === wifiManager.WifiConnState.WIFI_DISCONNECTED) {
        isResolved = true;
        clearTimeout(timer);
        resolve(false);
      }
    });

    // 发起连接
    wifiManager.connectToNetwork(networkId);
  });
}

4.4 SSID编码问题

坑点:中文SSID或特殊字符SSID需要正确编码。

// ❌ 错误:直接使用中文字符串
const ssid = '我的WiFi';

// ✅ 正确:转换为UTF-8编码
function encodeSsid(ssid: string): string {
  // 对于特殊字符,可能需要额外处理
  return ssid;
}

// 读取时注意解码
function decodeSsid(encodedSsid: string): string {
  // 处理读取到的SSID
  return encodedSsid;
}

4.5 多次连接问题

坑点:重复添加相同网络配置会创建多个配置项。

/**
 * 智能连接:先检查是否已存在配置
 */
async function smartConnect(ssid: string, password: string): Promise<boolean> {
  try {
    // 获取已保存的网络配置
    const configs = await wifiManager.getDeviceConfigs();
    
    // 查找是否已存在
    const existingConfig = configs.find(config => config.ssid === ssid);
    
    if (existingConfig) {
      // 更新密码并连接
      await wifiManager.updateDeviceConfig(existingConfig.networkId, {
        ...existingConfig,
        preSharedKey: password
      });
      return await wifiManager.connectToNetwork(existingConfig.networkId);
    } else {
      // 添加新配置并连接
      const networkId = await wifiManager.addDeviceConfig({
        ssid: ssid,
        preSharedKey: password,
        securityType: wifiManager.WifiSecurityType.WIFI_SEC_TYPE_PSK
      });
      return await wifiManager.connectToNetwork(networkId);
    }
  } catch (error) {
    console.error('[WiFi] 智能连接失败:', error);
    return false;
  }
}

五、HarmonyOS 6适配

5.1 API变更

HarmonyOS 6对WiFi API进行了部分调整:

API HarmonyOS 5 HarmonyOS 6 说明
getScanResults() 同步返回 异步Promise 改为异步调用
addDeviceConfig() 返回networkId 返回完整配置对象 返回值结构变化
connectToNetwork() networkId参数 支持配置对象 参数类型扩展

适配代码

/**
 * HarmonyOS 6适配的WiFi连接
 */
async function connectWifiAdaptive(ssid: string, password: string): Promise<boolean> {
  try {
    // 检测API版本
    const apiVersion = getApiVersion(); // 需要自行实现版本检测

    if (apiVersion >= 6) {
      // HarmonyOS 6 新写法
      const config: wifiManager.WifiDeviceConfig = {
        ssid: ssid,
        preSharedKey: password,
        securityType: wifiManager.WifiSecurityType.WIFI_SEC_TYPE_PSK
      };
      
      const result = await wifiManager.addDeviceConfig(config);
      // result 包含完整的配置信息
      return await wifiManager.connectToDevice(result);
    } else {
      // HarmonyOS 5 兼容写法
      const networkId = await wifiManager.addDeviceConfig({
        ssid: ssid,
        preSharedKey: password,
        securityType: wifiManager.WifiSecurityType.WIFI_SEC_TYPE_PSK
      });
      return await wifiManager.connectToNetwork(networkId);
    }
  } catch (error) {
    console.error('[WiFi] 连接失败:', error);
    return false;
  }
}

5.2 权限模型变更

HarmonyOS 6引入了更细粒度的权限控制:

// HarmonyOS 6 新增权限
{
  "requestPermissions": [
    {
      "name": "ohos.permission.GET_WIFI_INFO",
      "reason": "获取WiFi信息"
    },
    {
      "name": "ohos.permission.SET_WIFI_INFO",
      "reason": "修改WiFi设置"
    },
    {
      "name": "ohos.permission.GET_WIFI_CONFIG",  // 新增
      "reason": "读取已保存配置"
    },
    {
      "name": "ohos.permission.SET_WIFI_CONFIG",  // 新增
      "reason": "修改已保存配置"
    },
    {
      "name": "ohos.permission.APPROXIMATELY_LOCATION",  // 新增:粗略位置
      "reason": "WiFi扫描需要"
    }
  ]
}

5.3 后台扫描限制

HarmonyOS 6对后台WiFi扫描有更严格的限制:

// 需要申请后台能力
{
  "module": {
    "abilities": [{
      "name": "MainAbility",
      "backgroundModes": ["wifiInteraction"]  // 新增后台WiFi交互能力
    }]
  }
}

5.4 新增API

HarmonyOS 6新增了一些实用API:

// 获取WiFi详细信息(包含频段、带宽等)
const detailedInfo = await wifiManager.getDetailedLinkedInfo();
console.info(`频段: ${detailedInfo.frequency} MHz`);
console.info(`带宽: ${detailedInfo.bandwidth} MHz`);

// 获取支持的WiFi标准
const capabilities = await wifiManager.getSupportedFeatures();
console.info(`支持WiFi 6: ${capabilities.includes('wifi6')}`);

// 设置WiFi节能模式
await wifiManager.setPowerMode(wifiManager.WifiPowerMode.POWER_SAVING);

六、总结

WiFi连接管理是鸿蒙应用开发中的基础能力,掌握它对于开发联网类应用至关重要。本文从原理到实践,全面讲解了WiFi管理的核心要点:

核心要点回顾

  1. 权限管理:WiFi操作需要申请相应权限,特别是位置权限不可遗漏
  2. 状态监听:通过事件回调实时感知WiFi状态变化,及时更新UI
  3. 扫描策略:合理控制扫描频率,避免被系统限制
  4. 连接处理:注意超时机制、重连逻辑、配置管理
  5. 异常处理:网络不稳定是常态,需要完善的错误处理和重试机制

最佳实践建议

  • 封装统一的WiFi管理类,避免代码分散
  • 实现智能扫描策略,根据场景动态调整
  • 完善日志记录,便于问题排查
  • 做好版本适配,保证兼容性

下一步学习

  • WiFi热点创建与管理(下一篇文章)
  • WiFi P2P点对点通信
  • 网络质量检测与优化
  • 多网络协同切换

WiFi连接管理看似简单,实则细节众多。希望本文能帮助你建立起完整的知识体系,在实际开发中少走弯路。记住,网络连接是用户体验的基础,稳定可靠才是王道!

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。