应用场景
在安卓app上,用户输入WiFi名称(SSID)和密码,试图连接这个WiFi。那么用户输入的WiFi就有各种情况了,这个WiFi可以没有密码,也可以通过不同的加密方式加密。而不同的加密方式,需要写不同的代码才能使WiFi连接成功。无论百度还是谷歌,搜出来的代码大都是针对WPA/WPA2加密方式的,即使有些考虑到了无密码和WEP加密方式的WiFi连接,代码也都写得不清不楚,看着实在糟心。于是在查阅了N多资料,看了WifiConfiguration的源码后,有了这篇文章。不保证本文的所有内容完全正确(因为我也只是半桶水),但至少可以给大家一条思路,供参考。
错误做法
先说说一个基本没啥卵用的做法吧。代码如下:
private int getSecurityType(WifiConfiguration config) {
if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) {
return SECURITY_PSK;
}
if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP) || config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)) {
return SECURITY_EAP;
}
return (config.wepKeys[0] != null) ? SECURITY_WEP : SECURITY_NONE;
}
这段代码是我在网上搜到的,很多地方都有引用到,应该是互抄。有什么问题呢?且不说通过密码管理方式倒推出加密方式的逻辑是否严谨,只说一点,方法的入参WifiConfiguration config从何而来。网上给了答案,通过wifiManager.getConfiguredNetworks()呀,这不就拿到了。请注意,wifiManager.getConfiguredNetworks()是获取配置好的网络连接,换句话说,你的设备曾经连上过这些WiFi,设备才能保存这些config。而我的诉求是在从没有连接过这些WiFi的情况下去连接,config并不存在。所以,这条路走不通,歇菜。
正确做法
正确的做法是:通过ScanResult获取WiFi的信息。
List results = wifiManager.getScanResults();
for (int i = 0; i < results.size(); i++) {
ScanResult item = (ScanResult) results.get(i);
}
代码很好理解,拿到扫描到的WiFi列表。
if (item.SSID.equals(ssid)) {
WifiConfiguration config = createWifiInfo(ssid, pwd, item);
int netID = wifiManager.addNetwork(config);
boolean bRet = wifiManager.enableNetwork(netID, true);
Log.d(TAG, (bRet ? "Connect wifi ok" : "Connect wifi failed") + ",ssid=" + item.SSID);
}
通过SSID锁定我们的目标WiFi,并生成连接需要的WifiConfiguration
private WifiConfiguration createWifiInfo(String SSID, String Password, ScanResult scanResult) {
WifiConfiguration config = new WifiConfiguration();
config.allowedAuthAlgorithms.clear();
config.allowedGroupCiphers.clear();
config.allowedKeyManagement.clear();
config.allowedPairwiseCiphers.clear();
config.allowedProtocols.clear();
config.SSID = "\"" + SSID + "\"";
config.status = WifiConfiguration.Status.ENABLED;
String firstCapabilities = scanResult.capabilities.substring(1, scanResult.capabilities.indexOf("]"));
String[] capabilities = firstCapabilities.split