6、连接WiFi(传统方式):WifiConfiguration配置、addNetwork与enableNetwork、连接开放网络与WPA2/WPA3网络
说到WiFi连接,很多新手第一反应就是「直接调用系统API不就行了?」。嗯,理论上确实如此,但实际项目中你会发现,坑比想象中多得多。今天我就带你手把手走一遍传统连接方式的完整流程。
6.1 传统连接方式的核心思路
在Android 10之前,连接WiFi主要靠三个步骤:
- 创建一个
WifiConfiguration对象,填好SSID和密码 - 调用
addNetwork()把配置添加到系统 - 调用
enableNetwork()让系统去连接这个网络
说白了,就是「先注册,再启用」。我刚开始做WiFi开发时,以为这跟连蓝牙一样简单,结果第一次测试就翻车了——明明配置对了,手机就是不连。后来才发现,是networkId没处理好。
6.2 WifiConfiguration配置详解
WifiConfiguration是连接WiFi的「身份证」。你需要告诉系统:这个WiFi叫什么名字、用什么加密方式、密码是多少。
我个人习惯把配置过程封装成一个工具方法,这样复用起来方便。来看一个开放网络的配置示例:
private WifiConfiguration createOpenNetworkConfig(String ssid) {
WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"" + ssid + "\"";
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
return config;
}
注意SSID必须用双引号包起来。我见过不少新手直接传config.SSID = ssid,结果死活连不上。为什么?因为系统解析时会把不带引号的SSID当成无效值。
再看WPA2/WPA3网络的配置:
private WifiConfiguration createSecureNetworkConfig(String ssid, String password, boolean isWpa3) {
WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"" + ssid + "\"";
config.preSharedKey = "\"" + password + "\"";
if (isWpa3) {
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE);
config.requirePMF = true; // WPA3必须启用PMF
} else {
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
}
return config;
}
这里有个坑:WPA3用的是SAE(Simultaneous Authentication of Equals)协议,而不是传统的WPA_PSK。我在项目中遇到过一台小米手机,明明支持WPA3,但配置时忘了设requirePMF,结果一直连不上。查了半天文档才发现,WPA3强制要求PMF(Protected Management Frames)为true。
6.3 addNetwork与enableNetwork的配合
配置好WifiConfiguration之后,下一步就是把它交给系统。流程是这样的:
- 调用
wifiManager.addNetwork(config),返回一个networkId - 如果
networkId为-1,说明添加失败 - 调用
wifiManager.enableNetwork(networkId, true),第二个参数表示禁用其他网络 - 调用
wifiManager.reconnect()触发重连
来看完整代码:
public boolean connectToWiFi(Context context, String ssid, String password, boolean isWpa3) {
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
// 1. 创建配置
WifiConfiguration config = createSecureNetworkConfig(ssid, password, isWpa3);
// 2. 添加网络
int networkId = wifiManager.addNetwork(config);
if (networkId == -1) {
Log.e("WiFiConnect", "添加网络失败,请检查SSID或密码");
return false;
}
// 3. 启用网络
boolean enabled = wifiManager.enableNetwork(networkId, true);
if (!enabled) {
Log.e("WiFiConnect", "启用网络失败");
return false;
}
// 4. 触发重连
boolean reconnected = wifiManager.reconnect();
return reconnected;
}
你想想看,为什么需要reconnect()?因为enableNetwork只是告诉系统「我想连这个」,但系统不一定会立即执行。加上reconnect()相当于推了一把。
enableNetwork返回true但实际没连上的情况。后来加了个延时再检查连接状态,问题就解决了。建议在reconnect()之后,用BroadcastReceiver监听WifiManager.NETWORK_STATE_CHANGED_ACTION来确认连接结果。
6.4 连接开放网络与WPA2/WPA3的差异
不同加密方式的连接逻辑,其实就体现在WifiConfiguration的配置上。我整理了一张对比表:
| 网络类型 | KeyMgmt设置 | preSharedKey | 额外要求 |
|---|---|---|---|
| 开放网络 | KeyMgmt.NONE |
不需要 | 无 |
| WPA2 | KeyMgmt.WPA_PSK |
密码(双引号包裹) | 无 |
| WPA3 | KeyMgmt.SAE |
密码(双引号包裹) | requirePMF = true |
| WPA2/WPA3混合 | KeyMgmt.WPA_PSK + KeyMgmt.SAE |
密码(双引号包裹) | 需同时设置两种KeyMgmt |
对于混合模式,配置代码要这样写:
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE);
config.requirePMF = true;
嗯,这里要注意:混合模式下,系统会自动选择最合适的加密方式。但有些老旧路由器虽然广播了WPA3,实际却不支持,这时候手机会降级到WPA2连接。
6.5 知识体系总览
下面这张图帮你理清传统WiFi连接的完整脉络:
6.6 避坑指南
最后,分享几个我踩过的坑:
- SSID必须带引号:这是最容易被忽略的。系统内部存储时会把引号去掉,但传入时必须加上。
- networkId会变化:如果之前已经添加过同一个网络,
addNetwork()会返回已有的networkId,而不是新建一个。所以不要假设每次返回的都是新ID。 - 权限问题:Android 8.1以上需要
ACCESS_FINE_LOCATION权限,否则getScanResults()会返回空列表。我曾在华为手机上调试了半天,最后发现是定位权限没开。 - WPA3兼容性:不是所有Android 10以上的手机都完美支持WPA3。建议在连接前先检查设备能力,或者做降级处理。
WifiNetworkSpecifier,那是Google推荐的新方式,代码更简洁,而且不需要CHANGE_WIFI_STATE权限。
好了,传统WiFi连接的核心内容就这些。代码量不大,但每个细节都可能让你翻车。记住:SSID加引号、networkId判-1、WPA3设PMF,这三点做到位,基本就不会出大问题。