WiFi配置管理:保存的网络列表、忘记网络与更新配置
各位好,今天我们来聊聊WiFi配置管理这块。说实话,这部分内容在平时开发中可能不太起眼,但一旦出了问题,排查起来特别头疼。我个人习惯把WiFi配置管理比作手机的「通讯录」——你存了谁、删了谁、改了谁的电话,都得有个清晰的逻辑。
在Android里,WiFi配置管理主要涉及三个操作:获取已保存的网络列表、忘记某个网络、更新已有网络的配置。这三个操作背后,其实都围绕着同一个核心对象——WifiConfiguration。
1. 获取已保存的网络列表
先说说怎么拿到手机里存着的WiFi列表。这个操作很简单,调用WifiManager.getConfiguredNetworks()就行。但这里有个坑——Android 10(API 29)开始,这个方法被标记为废弃了。
为什么会这样?因为Google觉得直接暴露所有已保存网络的详细信息不太安全。你想想看,如果某个恶意应用拿到了这个列表,它就能知道你常去哪些地方、连过哪些热点。所以从Android 10开始,推荐用WifiManager.getPrivilegedConfiguredNetworks(),但这个需要SYSTEM_ALERT_WINDOW权限,普通应用基本拿不到。
来看一段示例代码:
WifiManager wifiManager = (WifiManager) getApplicationContext()
.getSystemService(Context.WIFI_SERVICE);
List<WifiConfiguration> networks = wifiManager.getConfiguredNetworks();
if (networks != null) {
for (WifiConfiguration config : networks) {
Log.d("WiFiConfig", "SSID: " + config.SSID
+ ", BSSID: " + config.BSSID
+ ", 优先级: " + config.priority);
}
}
这段代码在Android 9及以下跑得挺好。但如果你要适配高版本,就得另想办法了——比如用WifiNetworkSuggestion或者干脆引导用户手动操作。
2. 忘记网络(forgetNetwork)
「忘记网络」说白了就是删除手机里保存的某个WiFi配置。调用WifiManager.forgetNetwork(int netId, ActionListener listener)即可。
这里有个细节:netId是从WifiConfiguration.networkId拿到的。每个已保存的网络都有一个唯一的ID,就像身份证号一样。我曾经在项目里犯过一个低级错误——把SSID当成了netId传进去,结果怎么都删不掉,还报了INVALID_ARGUMENT错误。
int netId = config.networkId; // 注意:不是SSID!
wifiManager.forgetNetwork(netId, new WifiManager.ActionListener() {
@Override
public void onSuccess() {
Log.d("WiFiConfig", "网络已忘记");
}
@Override
public void onFailure(int reason) {
Log.e("WiFiConfig", "忘记失败,原因码: " + reason);
}
});
3. 更新网络配置
更新配置的场景其实挺常见的。比如用户改了WiFi密码、或者你想调整某个热点的优先级。更新操作本质上就是「先删除旧的,再添加新的」——但Android提供了一个更优雅的方式:WifiManager.updateNetwork(WifiConfiguration config)。
这个方法会返回一个int值:
| 返回值 | 含义 |
|---|---|
| -1 | 更新失败 |
| 其他值 | 更新后的networkId |
更新时要注意:必须保证WifiConfiguration对象里的networkId是有效的。如果你传了一个新的WifiConfiguration对象但没设置networkId,系统会认为你想添加一个新网络,而不是更新。
// 先获取已有的配置
WifiConfiguration config = findConfigBySSID("MyHomeWiFi");
if (config != null) {
// 修改密码
config.preSharedKey = "\"new_password_123\"";
config.priority = 1;
int result = wifiManager.updateNetwork(config);
if (result != -1) {
wifiManager.saveConfiguration(); // 别忘了保存!
Log.d("WiFiConfig", "更新成功,新networkId: " + result);
} else {
Log.e("WiFiConfig", "更新失败");
}
}
wifiManager.saveConfiguration(),否则修改不会持久化。这个步骤很容易被忽略,我刚开始做WiFi开发时就漏过好几次。
4. 知识体系总览
下面这张图把WiFi配置管理的核心逻辑串起来了:
5. 避坑指南
最后,我把自己这些年踩过的坑整理一下:
- 权限问题:操作WiFi配置需要
ACCESS_FINE_LOCATION和ACCESS_WIFI_STATE权限。Android 10以上还需要ACCESS_BACKGROUND_LOCATION。我曾经因为没申请后台定位权限,导致在后台更新配置时直接崩溃。 - 线程问题:
getConfiguredNetworks()是同步调用,不要在UI线程里执行。我习惯用AsyncTask或者协程来处理。 - SSID格式:保存配置时,SSID必须带双引号,比如
"MyWiFi"。但getConfiguredNetworks()返回的SSID可能带也可能不带引号,不同厂商的ROM行为不一致。我的处理方式是统一用WifiManager.ssidToWifiConfig()来转换。 - saveConfiguration()已废弃:从Android 8.0开始,
saveConfiguration()被标记为废弃。实际上,在Android 8.0以上,updateNetwork()会自动保存,不需要再手动调用。但为了兼容低版本,我一般还是会加上这个调用。
好了,关于WiFi配置管理的内容就聊到这里。这部分虽然看起来简单,但涉及到的细节和兼容性问题确实不少。希望今天的分享能帮你少走一些弯路。