ASCF Wi-Fi 信息获取与连接 API 实战:权限、列表与踩坑
在鸿蒙元服务开发中,Wi-Fi 相关的操作场景很常见,比如读取当前连接的网络信息、扫描周边可用热点、或者主动连接指定 Wi-Fi。ASCF 提供了一套覆盖这些场景的 Wi-Fi API,整体上手不算复杂,但权限配置和异步回调模式有一些容易踩的坑。本文基于实际使用经验,梳理 Wi-Fi 信息获取与连接的 API 用法、权限申请方式,以及开发过程中需要注意的关键点。## 权限配置:四个权限一个都不能少
ASCF Wi-Fi API 的权限体系比较繁琐,大部分接口除了 Wi-Fi 自身权限外,还要申请位置权限。原因是 Wi-Fi 列表和热点信息可以被用来做定位,系统因此将其归入位置权限管理。在 module.json5 中,通常需要声明以下四个权限:
{
"requestPermissions": [
{
"name": "ohos.permission.GET_WIFI_INFO",
"reason": "用于获取Wi-Fi信息",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
},
{
"name": "ohos.permission.SET_WIFI_INFO",
"reason": "用于连接Wi-Fi",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
},
{
"name": "ohos.permission.LOCATION",
"reason": "用于获取Wi-Fi位置信息",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
},
{
"name": "ohos.permission.APPROXIMATELY_LOCATION",
"reason": "用于获取Wi-Fi位置信息",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
}
]
}
除了静态声明,运行时还需要申请 scope.userLocation 授权。只有在授权成功后才能正常调用 Wi-Fi API。这一点很容易被忽略,尤其是当业务逻辑本身不涉及地图或定位时,开发者可能会觉得位置权限多余,但实际不申请就会直接调用失败。
has.authorize({
scope: 'scope.userLocation',
success: () => {
console.info('位置授权成功');
// 现在可以调用 Wi-Fi API 了
},
fail: (err) => {
console.error('位置授权失败:', err);
}
});
## 获取当前连接的 Wi-Fi 信息
授权通过后,通过 has.getConnectedWifi 可以拿到当前连接的热点信息,包括 SSID、BSSID、信号强度、频段和是否加密等。
has.authorize({
scope: 'scope.userLocation',
success: () => {
has.getConnectedWifi({
success: (res) => {
const wifi = res.wifi;
console.info('SSID:', wifi.SSID);
console.info('BSSID:', wifi.BSSID);
console.info('信号强度:', wifi.signalStrength);
console.info('频段:', wifi.frequency, 'MHz');
console.info('是否安全:', wifi.secure);
},
fail: (err) => {
console.error('获取失败:', err);
}
});
}
});
如果业务场景只需要展示当前 Wi-Fi 的名称,不需要信号强度等信息,可以将 partialInfo 参数设为 true,这样只会返回 SSID 和 BSSID,减少不必要的数据传输,同时也能降低部分权限要求。
has.getConnectedWifi({
partialInfo: true,
success: (res) => {
console.info('SSID:', res.wifi.SSID);
// 其他字段不会返回
}
});
## 获取 Wi-Fi 列表:先注册监听,再发起请求
扫描周围 Wi-Fi 列表的接口设计比较特殊:has.getWifiList 的 success 回调只代表列表请求已经发出,真正的 Wi-Fi 列表数据需要通过 has.onGetWifiList 监听返回。也就是说,必须先注册监听器,再调用 getWifiList,否则会收不到列表数据。
has.authorize({
scope: 'scope.userLocation',
success: () => {
// 先注册监听,再请求列表
has.onGetWifiList(function (res) {
const wifiList = res.wifiList;
console.info('发现', wifiList.length, '个 Wi-Fi');
wifiList.forEach(function (wifi) {
console.info(wifi.SSID, wifi.signalStrength);
});
});
// 请求获取列表
has.getWifiList({
success: () => {
console.info('Wi-Fi 列表请求成功');
},
fail: (err) => {
console.error('获取列表失败:', err);
}
});
}
});
这种“监听回调 + 请求触发”的模式,在 AS CF 的异步接口中比较常见,和普通的“请求-响应”模型不太一样。建议在页面加载时注册监听,在页面销毁时记得移除,避免内存泄漏。
## 连接指定 Wi-Fi
has.connectWifi 用于主动连接某个热点。需要注意的是,password 参数是必填的,即使是开放网络也要传空字符串,不能省略。
has.authorize({
scope: 'scope.userLocation',
success: () => {
has.connectWifi({
SSID: 'MyWiFi',
password: 'mypassword123',
success: () => {
console.info('Wi-Fi 连接成功');
has.showToast({ title: '连接成功' });
},
fail: (err) => {
console.error('连接失败:', err);
}
});
}
});
connectWifi 还有一个 manual 参数。如果设为 true,API 不会直接发起连接,而是跳转到系统 Wi-Fi 设置页面,让用户手动选择网络并输入密码。这种模式适合不确定密码、或者需要用户主动确认的场景,体验上更像是“引导用户去设置”,而不是应用内直接控制。
## 监听 Wi-Fi 连接状态
如果需要在连接状态变化时收到通知,可以使用 onWifiConnected 注册监听。注意,移除监听时要传入同一个函数对象,否则无法移除。用匿名函数注册的话,后续就没法单独解除监听,所以建议把回调函数保存成变量。
// 定义回调函数(需要保存引用才能移除)
const onConnected = function (res) {
const wifi = res.wifi;
console.info('Wi-Fi 已连接:', wifi.SSID);
};
// 注册监听
has.onWifiConnected(onConnected);
// 移除监听(需要传同一个函数对象)
has.offWifiConnected(onConnected);
// 或者移除所有监听
has.offWifiConnected();
另外,ASCF 还提供了 onWifiConnectedWithPartialInfo 接口,这个 API 从 1.0.14 版本才开始支持。它和 onWifiConnected 的区别在于只返回部分 Wi-Fi 信息,适用于只需要知道当前连接了哪个热点的场景,权限要求也更低。在不需要完整信息时,优先使用这个接口会更轻量。
## 实际开发中容易踩的坑
结合上面的 API 使用,有几个问题在开发时尤其容易遇到:
1. 必须先授权再操作。大部分 Wi-Fi API 依赖 scope.userLocation 授权,不授权直接调用会失败。很多开发者以为只有获取位置才需要位置权限,结果在 Wi-Fi 接口上栽了跟头。
2. getWifiList 的结果在监听回调里返回。getWifiList 的 success 回调只表示请求发出去了,真正的数据要等 onGetWifiList 触发。顺序必须是先注册监听,再调用 getWifiList。
3. 移除监听要传同一个函数对象。如果注册时用的是匿名函数,就无法单独移除,只能调用 offWifiConnected 不带参数来移除所有监听。这会带来潜在的风险,建议始终用变量保存回调引用。
4. signalStrength 不是 dBm。返回的信号强度是一个 0 到 1 之间的浮点数,1 表示最强,0 表示最弱。如果要显示信号图标,可以按 0.25 一档来划分等级,而不是直接用 dBm 去套。
5. connectWifi 的密码必填。即使连接的是开放网络,password 参数也必须传,传空字符串 '' 即可。
## API 方法速查
- has.getConnectedWifi:获取当前连接的 Wi-Fi 信息,支持 partialInfo 精简返回。
- has.getWifiList + has.onGetWifiList:获取并监听 Wi-Fi 列表,先注册监听再请求。
- has.connectWifi:连接指定 Wi-Fi,支持 manual 跳转系统设置。
- has.onWifiConnected / has.offWifiConnected:监听/移除 Wi-Fi 连接状态。
- has.onWifiConnectedWithPartialInfo:轻量级连接状态监听,仅返回部分信息,1.0.14 起可用。
整体来看,ASCF Wi-Fi API 的权限要求确实偏多,module.json5 里需要声明四个权限,运行时还要再申请位置授权。但接口本身的设计逻辑并不复杂,只要理解了“先注册监听再请求”这个模式,再注意权限和回调用引用的问题,日常的 Wi-Fi 获取与连接需求基本都能顺利实现。
Re: ASCF Wi-Fi 信息获取与连接 API 实战:权限、列表与踩坑
感谢分享,正好最近在做元服务里的 Wi-Fi 模块,这篇实战经验很有用。尤其“先注册监听再请求列表”这个点,官方文档写得比较含蓄,第一次很容易掉进去。 不过有个地方想请教一下:文中权限配置里写的是 `ohos.permission.SET_WIFI_INFO`,但我在项目里好像没找到这个权限,只有 `ohos.permission.SET_WIFI_INFO` 还是 `ohos.permission.MANAGE_WIFI`?另外代码里调用的是 `has.authorize`、`has.getConnectedWifi` 这些,是不是笔误?我这边用的是 `wifiManager` / `wifi` 的命名,可能不同版本 API 有差异?希望能确认下,免得新手照着抄又踩坑。Re: ASCF Wi-Fi 信息获取与连接 API 实战:权限、列表与踩坑
感谢楼主分享,非常实用!权限这块确实是坑,之前做类似功能时忘了动态申请位置权限,结果接口一直报错,排查了好久。 想请教一下:`onGetWifiList` 监听器注册后,如果页面销毁或不再需要列表,需要调用对应的 `offGetWifiList` 解除监听吗?另外,`getWifiList` 扫描的触发频率有没有限制?连续调用会不会被系统拦截?Re: ASCF Wi-Fi 信息获取与连接 API 实战:权限、列表与踩坑
楼主的总结很实用,尤其是权限和回调那块的坑,确实容易踩。我也补充一个点:元服务里动态申请 `scope.userLocation` 时,如果用户拒绝了,后续再调用 `has.authorize` 不一定立刻弹窗,最好先检查一下当前授权状态,避免静默失败。另外 `partialInfo` 那个参数能省权限这点挺有用的,没想到还能这么玩。
页:
[1]