微信小程序连接Wi-Fi:从权限申请到实战避坑指南

微信小程序连接Wi-Fi:从权限申请到实战避坑指南
1. 微信小程序连接Wi-Fi的前置准备第一次给小程序加Wi-Fi功能时我踩了不少坑。最让人头疼的是明明代码照着文档写了但死活连不上Wi-Fi。后来才发现微信小程序的Wi-Fi功能需要双重权限不仅要获取用户位置权限还得先调用专门的API启动Wi-Fi模块。这里有个冷知识为什么连接Wi-Fi需要位置权限因为从Android 6.0开始系统把Wi-Fi扫描结果归类为敏感位置信息。我当初也不理解直到看到官方解释才恍然大悟。具体操作分两步走先在app.json里声明权限{ permission: { scope.userLocation: { desc: 需要获取您的位置信息以连接Wi-Fi } } }实际调用前用wx.authorize弹窗请求授权wx.authorize({ scope: scope.userLocation, success: () { console.log(位置授权成功) this.startWifiProcess() // 开始连接流程 }, fail: () { wx.showModal({ title: 提示, content: 需要位置权限才能连接Wi-Fi, showCancel: false }) } })遇到过最坑的情况是用户第一次拒绝授权后再次调用wx.authorize会直接失败。这时候得用wx.openSetting引导用户去设置页手动开启权限。建议在fail回调里加上这层处理我吃过这个亏用户投诉说点了允许还是用不了其实就是没处理好授权拒绝后的流程。2. Wi-Fi连接的核心API详解真正开始连接Wi-Fi时你会发现微信提供了三个关键APIstartWifi、connectWifi和getWifiList。刚开始我误以为直接调用connectWifi就行结果各种报错。后来才明白必须按固定顺序调用startWifi- 启动Wi-Fi模块getWifiList可选- 获取周边Wi-Fi列表connectWifi- 连接指定网络这里有个性能优化点startWifi其实是异步操作官方文档没明说。我实测发现部分安卓机需要200-500ms初始化时间。最佳实践是用Promise封装function startWifi() { return new Promise((resolve, reject) { wx.startWifi({ success: resolve, fail: () { wx.showToast({ title: Wi-Fi模块启动失败, icon: none }) reject() } }) }) } // 使用时 await startWifi().catch(() {})connectWifi的参数配置是另一个重灾区。SSID和BSSID的区别就像小区名和门牌号SSID是无线网络名称如TP-Link_123BSSID则是路由器的MAC地址如a1:b2:c3:d4:e5:f6。在以下场景必须用BSSID同一场所存在多个同名Wi-Fi需要精确连接5GHz频段的路由器企业级网络中有多个AP发射相同SSID实测代码建议这样写wx.connectWifi({ SSID: 办公室Wi-Fi, BSSID: a1:b2:c3:d4:e5:f6, // 可选但建议填写 password: 12345678, success: () { wx.hideLoading() this.setData({ wifiStatus: connected }) }, fail: (err) { console.error(连接失败, err) // 特别处理密码错误情况 if (err.errCode 12002) { wx.showModal({ title: 提示, content: Wi-Fi密码错误 }) } } })3. Android高版本的兼容性难题去年我们上线Wi-Fi功能后突然收到大量安卓用户投诉连上Wi-Fi后退出小程序就断网。查了三天才发现是Android 10引入的后台限制除非应用有前台服务否则不能保持Wi-Fi连接。这个坑微信官方文档其实有说明但很容易被忽略。解决方案是用manual参数触发系统级连接wx.connectWifi({ SSID: 酒店Wi-Fi, password: room123, manual: true, // 关键参数 success: () { // 这里会有误导实际此时还未连接 wx.showToast({ title: 正在跳转系统设置 }) } })注意manual模式的特殊表现会跳转到系统Wi-Fi设置页用户需要手动点击连接按钮连接状态无法实时同步回小程序为了提升用户体验我推荐配合wx.onWifiConnected监听事件wx.onWifiConnected((result) { if (result.WiFi.SSID 酒店Wi-Fi) { wx.showToast({ title: 系统连接成功 }) } })还有个隐藏坑点部分华为/小米手机会修改系统Wi-Fi设置页导致manual模式失效。针对这些机型我们最终加了机型判断逻辑检测到特定机型就显示图文引导教程。收集到的需要特殊处理的机型包括华为Mate30系列小米10及更新机型OPPO ColorOS 11以上系统4. 企业级场景的进阶实践给商场做智能导航小程序时遇到了更复杂的需求需要自动连接商场的多个热点且不能反复弹授权。这时候就需要服务端配合的方案了服务端预置各楼层AP的BSSID列表小程序获取当前连接的BSSID匹配到预设BSSID时自动切换楼层关键代码如下// 获取当前连接信息 wx.getConnectedWifi({ success: (res) { const { BSSID } res.wifi // 调用后端接口匹配楼层 wx.request({ url: https://api.example.com/locate, data: { bssid: BSSID }, success: (resp) { this.setData({ currentFloor: resp.data.floor }) } }) } })对于需要频繁切换Wi-Fi的场景建议使用Wi-Fi列表缓存。我实测发现连续调用getWifiList会有3秒间隔限制解决方法是在内存中维护一个缓存let wifiCache { timestamp: 0, list: [] } function getWifiList() { // 缓存有效期内直接返回 if (Date.now() - wifiCache.timestamp 3000) { return Promise.resolve(wifiCache.list) } return new Promise((resolve) { wx.getWifiList({ success: () { wx.onGetWifiList((res) { wifiCache { timestamp: Date.now(), list: res.wifiList } resolve(res.wifiList) }) } }) }) }在商场这类复杂环境还会遇到信号强度判断问题。iOS获取的signalStrength范围是0-100而安卓是负数-100到0。我们统一处理为百分比显示function formatSignal(wifi) { // iOS处理 if (wifi.signalStrength 0) { return wifi.signalStrength % } // 安卓处理 return (100 wifi.signalStrength) % }这些经验都是从真实项目踩坑总结出来的。特别是信号强度计算最初没做平台区分导致安卓机永远显示信号强度0%被客户骂惨了。现在回想起来做Wi-Fi功能最考验的不是技术难度而是对各种手机厂商系统差异的兼容处理。