在移动应用开发中,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 = false
build() {
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相关功能。