鸿蒙NEXT Wi-Fi扫描开发指南:从基础到实战
在移动应用开发中,Wi-Fi扫描功能是实现网络连接、位置服务等功能的基石,掌握鸿蒙NEXT的Wi-Fi开发能力至关重要。
在鸿蒙应用开发中,Wi-Fi管理是常见的需求之一。无论是扫描附近热点、连接指定网络,还是获取网络状态,鸿蒙NEXT都提供了一套完整的API。
本文将带你全面了解鸿蒙NEXT中Wi-Fi扫描的开发方法,从基础概念到实战应用,帮助你快速掌握这一核心技能。
一、Wi-Fi扫描基础概念
在鸿蒙NEXT中,Wi-Fi扫描主要涉及Station模式。STA是支持IEEE802.11协议的设备,通常指具有Wi-Fi client行为的设备,可以连接到接入点。
STA会扫描可连接的接入点,选择一个想要连接的接入点,经过认证、关联等步骤后,与接入点建立连接。
Wi-Fi扫描有两种不同的方式:
主动扫描:由Wi-Fi client在每个信道上发送探测请求帧,接入点收到探测请求后返回探测响应
被动扫描:Wi-Fi Client在每个信道上监听接入点发出的信标帧
二、开发前准备
1. 模块导入
在鸿蒙NEXT中,Wi-Fi相关功能主要通过@ohos.wifiManager
或@kit.ConnectivityKit
模块提供:
javascript
import wifi from '@ohos.wifi'; // API version 6及以上 // 或 import { wifiManager } from '@kit.ConnectivityKit';
2. 权限声明
在module.json5
配置文件中声明必要的Wi-Fi权限:
json
{"module": {"requestPermissions": [{"name": "ohos.permission.GET_WIFI_INFO","reason": "需要获取Wi-Fi信息","usedScene": {"abilities": ["MainAbility"],"when": "always"}},{"name": "ohos.permission.SET_WIFI_INFO","reason": "需要配置Wi-Fi连接","usedScene": {"abilities": ["MainAbility"],"when": "always"}},{"name": "ohos.permission.LOCATION","reason": "需要访问位置信息以进行Wi-Fi扫描","usedScene": {"abilities": ["MainAbility"],"when": "always"}}]} }
注意:某些API如getScanInfos()
需要ohos.permission.GET_WIFI_INFO
以及ohos.permission.GET_WIFI_PEERS_MAC
和ohos.permission.LOCATION
权限中的至少一个。
三、Wi-Fi扫描实现
1. 检查Wi-Fi状态
在进行Wi-Fi扫描前,应先检查Wi-Fi是否已激活:
javascript
import wifi from '@ohos.wifi';// 查询WLAN是否已激活 let isActive = wifi.isWifiActive(); console.log(`Wi-Fi is active: ${isActive}`);// 如果Wi-Fi未激活,需要先启用 if (!isActive) {// 注意:需要ohos.permission.MANAGE_WIFI_SETTINGS权限wifi.enableWifi(); }
2. 启动Wi-Fi扫描
使用scan()
方法启动Wi-Fi扫描:
javascript
// 启动WLAN扫描 let scanResult = wifi.scan(); if (scanResult) {console.log("Wi-Fi扫描启动成功"); } else {console.error("Wi-Fi扫描启动失败"); }
scan()
方法需要ohos.permission.SET_WIFI_INFO
和ohos.permission.LOCATION
权限,返回true
表示扫描操作执行成功,false
表示扫描操作执行失败。
3. 获取扫描结果
获取扫描结果有两种异步方式:Promise和callback。
使用Promise方式:
javascript
wifi.getScanInfos().then(result => {let len = Object.keys(result).length;console.log("Wi-Fi扫描结果数量: " + len);for (let i = 0; i < len; ++i) {console.info("SSID: " + result[i].ssid);console.info("BSSID: " + result[i].bssid);console.info("信号强度: " + result[i].rssi);console.info("安全类型: " + result[i].securityType);console.info("频段: " + result[i].band);console.info("频率: " + result[i].frequency);} }).catch(error => {console.error("获取扫描结果失败: " + error); });
使用Callback方式:
javascript
wifi.getScanInfos((err, result) => {if (err) {console.error("获取扫描结果错误: " + JSON.stringify(err));return;}var len = Object.keys(result).length;console.log("Wi-Fi接收到扫描信息: " + len);for (var i = 0; i < len; ++i) {console.info("SSID: " + result[i].ssid);console.info("BSSID: " + result[i].bssid);console.info("能力: " + result[i].capabilities);console.info("安全类型: " + result[i].securityType);console.info("信号强度: " + result[i].rssi);console.info("频段: " + result[i].band);console.info("频率: " + result[i].frequency);console.info("信道宽度: " + result[i].channelWidth);console.info("时间戳: " + result[i].timestamp);} });
4. 扫描结果数据结构
获取到的扫描结果是WifiScanInfo
对象的数组,包含以下属性:
字段名 | 类型 | 说明 |
---|---|---|
ssid | string | 热点的SSID,编码格式为UTF-8 |
bssid | string | 热点的BSSID |
capabilities | string | 热点能力 |
securityType | WifiSecurityType | WLAN加密类型 |
rssi | number | 热点的信号强度(dBm) |
band | number | WLAN接入点的频段 |
frequency | number | WLAN接入点的频率 |
channelWidth | number | WLAN接入点的带宽 |
timestamp | number | 时间戳 |
四、高级功能与实战应用
1. 获取信号等级
可以根据信号强度(rssi)和频段(band)获取用户更易理解的信号等级:
javascript
import { wifiManager } from '@kit.ConnectivityKit';// 对扫描结果按信号强度排序 let scanList = wifiManager.getScanInfoList().sort((a, b) => {return wifiManager.getSignalLevel(b.rssi, b.band) - wifiManager.getSignalLevel(a.rssi, a.band); });// 显示带信号等级的Wi-Fi列表 scanList.forEach((wifiInfo, index) => {let signalLevel = wifiManager.getSignalLevel(wifiInfo.rssi, wifiInfo.band);console.log(`${index + 1}. SSID: ${wifiInfo.ssid}, 信号等级: ${signalLevel}/5`); });
2. 连接Wi-Fi热点
扫描到Wi-Fi热点后,通常需要连接功能:
javascript
async function connectToWifi(wifiInfo, password) {try {// 如果已连接,先断开当前连接if (wifiManager.isConnected()) {// 这里添加断开连接的逻辑}// 创建Wi-Fi设备配置let config = {ssid: wifiInfo.ssid,preSharedKey: password,securityType: wifiInfo.securityType};// 添加候选网络配置let netId = await wifiManager.addCandidateConfig(config);// 连接到候选网络wifiManager.connectToCandidateConfig(netId);console.log("开始连接Wi-Fi");} catch (error) {console.error("连接Wi-Fi失败: " + JSON.stringify(error));} }
注意:connectToCandidateConfig
和addCandidateConfig
方法需要ohos.permission.SET_WIFI_INFO
权限。
3. 获取当前连接信息
获取当前连接的Wi-Fi信息:
javascript
// 获取当前连接的Wi-Fi信息 wifiManager.getLinkedInfo().then(data => {console.info("获取Wi-Fi连接信息: " + JSON.stringify(data)); }).catch(error => {console.info("获取连接信息错误"); });
4. 监听网络状态变化
实时监控网络状态变化对于提供良好的用户体验至关重要:
javascript
import { connection } from '@kit.NetworkKit';// 创建网络连接监听器 const netConnection = connection.createNetConnection();// 监听网络可用事件 netConnection.on('netAvailable', (netHandle) => {console.log(`🎉 网络切换成功!新网络ID:${netHandle.netId}`); });// 监听网络丢失事件 netConnection.on('netLost', (netHandle) => {console.log('网络连接丢失'); });// 注册监听 netConnection.register();// 在适当的时候取消监听 // netConnection.unregister();
五、完整示例
以下是一个完整的Wi-Fi扫描与连接示例:
javascript
import { wifiManager } from '@kit.ConnectivityKit'; import { connection } from '@kit.NetworkKit';@Entry @Component struct WifiScanner {@State wifiList: Array<wifiManager.WifiScanInfo> = []@State isScanning: boolean = false// 扫描Wi-Fi热点scanWifi() {this.isScanning = true// 注意:实际开发中需要处理权限请求try {let result = wifiManager.scan();if (result) {// 模拟扫描延迟,实际开发中使用事件监听setTimeout(() => {this.wifiList = wifiManager.getScanInfoList().sort((a, b) => {return wifiManager.getSignalLevel(b.rssi, b.band) - wifiManager.getSignalLevel(a.rssi, a.band);});this.isScanning = false;}, 3000);}} catch (error) {console.error("扫描失败: " + JSON.stringify(error));this.isScanning = false;}}// 连接Wi-Fi热点async connectToWifi(wifiInfo: wifiManager.WifiScanInfo, password: string) {try {if (wifiManager.isConnected()) {// 提示用户先断开当前连接console.log("请先断开当前Wi-Fi连接");return;}let config = {ssid: wifiInfo.ssid,preSharedKey: password,securityType: wifiInfo.securityType};let netId = await wifiManager.addCandidateConfig(config);wifiManager.connectToCandidateConfig(netId);console.log("开始连接至: " + wifiInfo.ssid);} catch (error) {console.error("连接失败: " + JSON.stringify(error));}}build() {Column() {Text('Wi-Fi热点扫描').fontSize(20).margin(10)Button(this.isScanning ? '扫描中...' : '扫描热点').onClick(() => {this.scanWifi();}).width('80%').margin(10).enabled(!this.isScanning)List() {ForEach(this.wifiList, (item: wifiManager.WifiScanInfo) => {ListItem() {WifiItem({wifiInfo: item,connectCallback: this.connectToWifi.bind(this)})}})}.layoutWeight(1).width('100%')}.height('100%')} }@Component struct WifiItem {@Param wifiInfo: wifiManager.WifiScanInfo@Param connectCallback: (wifiInfo: wifiManager.WifiScanInfo, password: string) => void@State password: string = ''@State showPasswordInput: boolean = falsebuild() {Column() {Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {Text(this.wifiInfo.ssid || '隐藏网络').fontSize(16).flexGrow(1)Text(`信号: ${wifiManager.getSignalLevel(this.wifiInfo.rssi, this.wifiInfo.band)}/5`).fontSize(12).margin({ right: 10 })Button('连接').onClick(() => {if (this.wifiInfo.securityType !== wifiManager.WifiSecurityType.WIFI_SEC_TYPE_OPEN) {this.showPasswordInput = true;} else {this.connectCallback(this.wifiInfo, '');}}).fontSize(12)}.width('100%')if (this.showPasswordInput) {TextInput({ placeholder: '输入Wi-Fi密码', text: this.password }).onChange((value: string) => {this.password = value;}).width('100%').margin({ top: 5 })Button('确认连接').onClick(() => {this.connectCallback(this.wifiInfo, this.password);this.showPasswordInput = false;}).width('100%').margin({ top: 5 })}}.padding(10).border({ width: 1, color: '#CCCCCC' }).margin({ top: 5, bottom: 5 })} }
六、常见问题与解决方案
1. 权限问题
问题:调用Wi-Fi相关API时返回权限错误。
解决:
确保在
module.json5
中声明了所需权限在运行时动态请求必要权限
检查权限名称是否正确
2. 扫描结果为空
问题:获取到的扫描结果列表为空。
解决:
检查是否已授予位置权限
确认Wi-Fi已启用
添加适当的延迟后再获取扫描结果
3. 连接失败
问题:无法连接到指定的Wi-Fi热点。
解决:
检查SSID和密码是否正确
确认安全类型匹配
确保设备不在飞行模式下
七、总结
通过本文,我们全面介绍了鸿蒙NEXT中Wi-Fi扫描的开发方法,包括:
基础概念:了解Wi-Fi扫描的两种方式
权限配置:正确声明和请求Wi-Fi相关权限
扫描实现:使用API进行Wi-Fi扫描和结果获取
高级功能:信号等级评估、热点连接和网络状态监听
实战示例:完整的Wi-Fi扫描和连接组件
Wi-Fi扫描是鸿蒙应用开发中的常见需求,掌握这些技能将为你的应用增添强大的网络功能。希望本文能帮助你在鸿蒙NEXT开发中顺利实现Wi-Fi相关功能。