NEHotspotConfiguration-apply行为与BSSID变化说明

1 阅读7分钟

NEHotspotConfiguration.applyConfiguration 行为与 BSSID 变化说明

1. 背景

本文整理 iOS NEHotspotConfigurationManager.applyConfiguration(_:completionHandler:) 的接口行为、iOS 系统底层 Wi-Fi 加入流程、扫描行为、BSSID 变化风险,以及在 OPPO 互传热点场景中的排查建议。

接口定义:

- (void)applyConfiguration:(NEHotspotConfiguration *)configuration
         completionHandler:(void (^ __nullable)(NSError * __nullable error))completionHandler API_AVAILABLE(ios(11.0), watchos(7.0)) API_UNAVAILABLE(macos, tvos);

该接口的核心作用是:App 将一个 Wi-Fi 配置提交给 iOS 系统,由系统尝试加入指定 SSID 的 Wi-Fi 网络

它不是 Wi-Fi 扫描接口,也不是底层连接控制接口。App 只能提交配置,真正的扫描、匹配、关联、认证、DHCP、网络切换均由 iOS 系统 Wi-Fi 服务处理。

2. applyConfiguration 的主要行为

2.1 配置校验

调用后,iOS 会先校验配置和运行环境,常见校验项包括:

  • App 是否具备 Hotspot Configuration entitlement。
  • SSID 是否合法。
  • 密码是否符合安全类型要求。
  • 安全类型是否匹配,例如开放网络、WPA/WPA2/WPA3、EAP 等。
  • 当前系统是否允许 App 添加该 Wi-Fi 配置。
  • 当前设备 Wi-Fi 是否可用。
  • 是否已有 pending 的 Wi-Fi 配置请求。

如果配置不合法,completionHandler 会返回 error。

2.2 系统接管 Wi-Fi 加入流程

配置通过后,iOS 底层通常会进入如下流程:

App 提交 Wi-Fi 配置
↓
iOS Wi-Fi 服务接管
↓
查找目标 SSID
↓
使用已有扫描缓存或触发 Wi-Fi 扫描
↓
选择一个 BSSID
↓
发起 Authentication / Association
↓
完成安全认证或四次握手
↓
DHCP 获取 IP
↓
更新当前网络状态
↓
回调 App

这些步骤均由系统控制,App 无法直接介入。

3. iOS 系统底层扫描行为

调用 applyConfiguration 后,iOS 底层通常会为了加入目标 Wi-Fi 执行扫描或使用已有扫描结果。

可能发生的行为包括:

  • 查询系统已有 Wi-Fi 扫描缓存。
  • 主动触发 Wi-Fi scan。
  • 多信道查找目标 SSID。
  • 对隐藏 SSID 发 Probe。
  • 目标 SSID 不可见时,短时间等待或重试扫描。
  • 根据系统策略停止扫描或放弃连接。

需要明确:

applyConfiguration 不是持续扫描 API。
扫描只是 iOS 为完成加入目标 SSID 而执行的内部动作。

App 不能控制或获取以下信息:

  • 扫描频率。
  • 扫描持续时间。
  • 扫描信道。
  • 扫描到的 Wi-Fi 列表。
  • 是否命中扫描缓存。
  • 具体选择了哪个 BSSID。
  • 系统何时停止扫描或放弃连接。

因此,业务逻辑不应依赖该接口实现“持续等待目标热点出现”的能力。系统可能短时间内等待或重试,但不保证无限持续扫描。

4. completionHandler 的语义

completionHandler(error == nil) 不严格等价于已经连上目标 Wi-Fi。

它更接近于:

系统接受了配置,并且加入流程没有立即失败。

因此可能出现以下情况:

apply error == nil
但当前 SSID 不是目标 SSID

或:

apply error == nil
SSID 已切换
但 IP / DHCP / TCP / WebSocket 不可用

互传业务不能只依赖 apply 回调判断 Wi-Fi 已连接成功。

5. 常见错误

常见 NEHotspotConfigurationError 包括:

invalid
invalidSSID
invalidWPAPassphrase
invalidWEPPassphrase
userDenied
pending
systemConfiguration
unknown

含义示例:

  • userDenied:用户拒绝加入。
  • pending:已有加入请求尚未完成。
  • systemConfiguration:系统配置失败。
  • invalidSSID:SSID 不合法。
  • invalidWPAPassphrase:WPA 密码不合法。
  • invalidWEPPassphrase:WEP 密码不合法。
  • unknown:系统未给出明确原因。

6. joinOnce 行为

如果设置:

configuration.joinOnce = true

表示一次性加入。

特点:

  • 系统不会长期保存为稳定自动加入网络。
  • App 退后台、锁屏、网络切换后,系统可能断开或不再自动重连。
  • 适合临时热点、设备配网、互传热点。
  • 不适合长期保持连接的 Wi-Fi。

如果 joinOnce = false,系统可能保存该网络,后续自动加入行为更接近普通 Wi-Fi。

7. BSSID 相关行为

7.1 SSID 与 BSSID

SSID  = Wi-Fi 名字
BSSID = 具体 AP 的 MAC 地址

同一个 SSID 可能对应多个 BSSID:

SSID: OPPO-Share
BSSID A: 2.4G AP
BSSID B: 5G AP
BSSID C: 6G AP

NEHotspotConfiguration 通常只指定 SSID,不指定 BSSID。具体连接哪个 BSSID 由 iOS 系统决定。

7.2 BSSID 是否会变化

BSSID 在连接过程中可能变化。

常见场景包括:

  • 同 SSID 多 AP 漫游。
  • 同一热点存在 2.4G / 5G / 6G 多频 BSSID。
  • OPPO 热点重启。
  • OPPO 热点切换频段。
  • 普通热点切换到高速热点。
  • SoftAP 使用随机 MAC 或虚拟 BSSID。
  • Wi-Fi 7 / MLO / 多链路场景。

如果是单一 OPPO SoftAP,且热点不重启、不切频,BSSID 通常较稳定。

7.3 BSSID 变化是否会导致连接失败

BSSID 变化有可能导致 Wi-Fi 连接失败,但不是所有 BSSID 变化都会失败。

高风险场景如下:

iOS 扫到 SSID=A, BSSID=1
↓
iOS 准备关联 BSSID=1
↓
OPPO 热点重启或切频
↓
BSSID=1 消失,变成 BSSID=2
↓
iOS 关联旧 BSSID 失败

还可能出现:

apply error == nil
但实际没有连上目标 SSID

或:

SSID 连上了
但 DHCP 未完成

或:

已连上后立即 deauth / disassoc

正常企业 Wi-Fi / Mesh 漫游中,如果 SSID、安全参数、网关、DHCP 环境一致,BSSID 从 A 切到 B 通常不会导致连接失败,最多出现短暂抖动。

8. OPPO 互传热点场景风险

在 iPhone 加入 OPPO 热点的互传流程中,热点生命周期较短,因此 BSSID 变化风险更明显。

典型流程:

OPPO 启动热点
↓
iOS 调 applyConfiguration
↓
OPPO 热点切频 / 重启 / BSSID 变化
↓
iOS 使用旧扫描结果尝试连接
↓
连接失败或超时

典型表现:

  • apply 返回 nil,但 SSID 未切换。
  • SSID 已切换,但 IP 不对。
  • DHCP 未完成。
  • WebSocket 连接失败。
  • 空口包看到 Association 后 Deauth。
  • OPPO 侧显示连接超时或传输超时。

9. 推荐成功判断

不要只判断:

apply error == nil

建议组合判断:

apply error == nil
+
当前 SSID == 目标 SSID
+
本机 IP 已获取
+
对端 IP / 端口可达
+
WebSocket / HTTP 连接成功

BSSID 可以记录并作为辅助判断,但不建议作为唯一成功条件。

10. 排查建议

10.1 App 日志

关注:

  • applyConfiguration start
  • apply callback
  • 当前 SSID
  • 当前 BSSID
  • 本机 IP
  • smartVerifySSID
  • WebSocket connect
  • HTTP download / upload start

10.2 iOS Wi-Fi / sysdiagnose / IPS

关注:

  • Association
  • Authentication
  • Deauthentication
  • Disassociation
  • AutoJoin
  • DHCP
  • BSSID change
  • SSID change
  • NEHotspot
  • wifid
  • airportd

10.3 空口包

关注:

  • Probe Request / Probe Response
  • Authentication Request / Response
  • Association Request / Response
  • EAPOL
  • Deauthentication
  • Disassociation
  • DHCP Discover / Offer / Request / Ack

10.4 OPPO 热点日志

关注:

  • 热点启动时间。
  • 热点 SSID。
  • 热点 BSSID。
  • 频段。
  • 是否重启热点。
  • 是否切换高速热点。
  • 是否有客户端关联。
  • 是否分配 IP。

11. 建议的业务流程

互传场景建议按以下流程处理:

OPPO 热点启动并稳定
↓
OPPO 通过 BLE 下发 SSID / 密码 / IP / port
↓
iOS 调 applyConfiguration
↓
等待 apply 回调
↓
轮询确认当前 SSID
↓
确认本机 IP / 网关 / 对端 IP 可达
↓
WebSocket 连接
↓
进入文件传输

如果失败:

SSID 不正确 → 重新 apply 或回退 BLE/热点流程
SSID 正确但 IP 不正确 → 等待 DHCP 或重试
IP 正确但端口不可达 → 检查 OPPO 服务是否启动
WebSocket 超时 → 检查热点稳定性、BSSID 是否变化、TCP 是否可达

12. 总结

applyConfiguration 是请求 iOS 加入指定 Wi-Fi 的接口,不是扫描接口。调用后,iOS 底层会为了加入目标 SSID 执行扫描、匹配、关联、认证、DHCP 等动作,但这些过程由系统控制,App 不可见也不可控。

BSSID 在连接过程中可能变化。如果 BSSID 变化发生在扫描、关联、认证、DHCP 这些关键窗口期,尤其是 OPPO 热点重启或切频导致旧 BSSID 消失,就可能导致 Wi-Fi 连接失败。

互传业务中,应以 SSID + IP + 对端可达 + WebSocket/HTTP 成功 作为最终成功判断,而不是只依赖 apply 回调或 BSSID。