WIFI的有关操作,系统提供了完备的API,供第三方app调用;
比如,开启和关闭wifi,获取wifi的状态,获取已保存的配置信息:getConfiguredNetworks()
,获取当前连接的网络信息:getConnectionInfo()
等。需要注意的是搜索网络(startScan()
)并不是同步调用,搜索网络的方法本身不会返回结果,而是搜索完成后,会收到WifiManager.SCAN_RESULTS_AVAILABLE_ACTION
类型的广播,在收到该广播后调用getScanResults()
才可获取到覆盖的网络信息,包括SSID、信号强度、加密类型等;此外,需注意断开某个网络,调用disableNetwork(netId)
方法后,对应的网络会进入已停用的状态,除非再次主动调用enableNetwork
方法激活该网络,否则系统都不会再自动连接到该网络。enableNetwork
可以传两个参数,其中第一个是网络id,第二个代表是否同时断开其他的网络,如果传递false就是代表仅做激活不一定连接(如果当前已经有连接就不会重新连接),如果传递true就是代表不仅做激活而且确保连接到当前传递的网络(如果当前已经有其他连接就会断开并重新连接)。
连接到某个网络enableNetwork(tempConfig.networkId, true)
时,也许有的小伙伴们会这么编码:
WifiConfiguration wifiConfig = CreateWifiInfo(SSID, Password);
if (wifiConfig == null) {
return false;
}
WifiConfiguration tempConfig = IsExsits(context, SSID);//判断是否已在配置网络集
if (tempConfig != null) {
wifiManager.removeNetwork(tempConfig.networkId);
}
int netID = wifiManager.addNetwork(wifiConfig);
boolean bRet = wifiManager.enableNetwork(netID, true);
但是在android 6.0及以上版本以上代码有问题。
android 6.0开始app只能修改自己创建的WifiConfiguration对象的状态,而不再允许修改或删除由用户或其它app创建的WifiConfiguration对象,因此addNetwork()
可能返回“-1”,从而导致执行enableNetwork
方法出错,因此最合适的做法参考如下:
WifiConfiguration tempConfig = IsExsits(SSID);
if (tempConfig != null) {
bRet = wifiManager.enableNetwork(tempConfig.networkId, true);
}else{
WifiConfiguration wifiConfig = CreateWifiInfo(SSID, Password);
if (wifiConfig == null) {
logd("wifiConfig create failed.");
return false;
}
int netID = wifiManager.addNetwork(wifiConfig);
bRet = wifiManager.enableNetwork(netID, true);
}
先判断要连接的网络信息是否已经在已配置列表中,如果在就直接调用enableNetwork
方法,否则就先创建再调用enableNetwork
方法,创建的方法参考如下:
private WifiConfiguration CreateWifiInfo(String SSID, String Password) {
WifiConfiguration config = new WifiConfiguration();
config.allowedAuthAlgorithms.clear();
config.allowedGroupCiphers.clear();
config.allowedKeyManagement.clear();
config.allowedPairwiseCiphers.clear();
config.allowedProtocols.clear();
config.SSID = "\"" + SSID + "\"";
config.preSharedKey = "\"" + Password + "\"";
config.hiddenSSID = true;
// [WPA2-PSK-TKIP]
config.preSharedKey = "\"" + Password + "\"";
// config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
config.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
config.status = WifiConfiguration.Status.ENABLED;
WifiConfiguration tempConfig = config;
if (tempConfig != null) {
}
return config;
}
热点的有关操作,系统就没有完全开放,除非你是具有系统签名的app。
比如,关闭、打开热点(设置SSID和密码,设置最大连接数,设置信道),获取热点状态,获取热点配置信息,判断热点是否开启等,基本都采用了反射,而且打开热点必须是系统签名的app才能正确执行。
private static boolean isWifiApEnabled(WifiManager wifiManager) {
try {
Method method = wifiManager.getClass().getMethod("isWifiApEnabled");
method.setAccessible(true);
return (Boolean) method.invoke(wifiManager);
} catch (NoSuchMethodException e) {
logd(e);
} catch (Exception e) {
logd(e);
}
return false;
}
public WifiConfiguration getApConfig() {
if (isWifiApEnabled(mWifiManager)) {
try {
Method method = mWifiManager.getClass().getMethod("getWifiApConfiguration");
method.setAccessible(true);
WifiConfiguration config = (WifiConfiguration) method.invoke(mWifiManager);
return config;
} catch (Exception e) {
logd(e);
}
}
return null;
}
public static boolean setWifiApEnabled(Context context, String ssid,
String key, Boolean enabled) {
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
if (enabled) { // disable WiFi in any case
// wifi和热点不能同时打,所以打热点的时候需要关闭wifi
setWifiEnable(context, false);
}
try {
// 热点的配置类
WifiConfiguration apConfig = new WifiConfiguration();
apConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
apConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
apConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
apConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
apConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
apConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
apConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
// 配置热点的名称(可以在名字后面加点随机数)
apConfig.SSID = ssid;
//设置信道 1 到11 之间的随机整数
apConfig.apChannel=new Random().nextInt(11)+1;
apConfig.softApMaxNumSta= AppConfig.numClients;
// 配置热点的密码
apConfig.preSharedKey = key;
// 配置加密方式
//apConfig.allowedKeyManagement.set(WPA2_PSK);
apConfig.allowedKeyManagement.set(1);
// 通过反射调用设置热点
Method method = wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, Boolean.TYPE);
// 返回热点打开状
return (Boolean) method.invoke(wifiManager, apConfig, enabled);
} catch (Exception e) {
logd("setWifiApEnabled:" + e.getMessage());
return false;
}
}