最近一直在做盒子上的setting,涉及到wifi设置。
android源生的wifi设置代码很复杂,我所工作的项目是在盒子上,不需要那么复杂的功能。
首先注册广播,这一部分直接使用源生的代码,修改了其中的一部分。
private WifiModel(Context context) {
mContext = context;
mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
mFilter = new IntentFilter();
// 注册广播
mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
mFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
mFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);
mFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
mFilter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
mFilter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);
mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
handleEvent(context, intent);
}
};
mScanner = new Scanner();
mContext.registerReceiver(mReceiver, mFilter);
}
// 处理广播
private void handleEvent(Context context, Intent intent) {
String action = intent.getAction();
Log.i(TAG, action);
// wifi状态改变
if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
updateWifiState(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN));
}
// Scanner通过调用mWifiManager.startScan()处理定时扫描wifi列表
else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action)
|| WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION.equals(action)
|| WifiManager.LINK_CONFIGURATION_CHANGED_ACTION.equals(action)) {
updateAccessPoints();
} else if (WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(action)) {
// Ignore supplicant state changes when network is connected
// TODO: we should deprecate SUPPLICANT_STATE_CHANGED_ACTION and
// introduce a broadcast that combines the supplicant and network
// network state change events so the apps dont have to worry about
// ignoring supplicant state change when network is connected
// to get more fine grained information.
SupplicantState supplicantState = (SupplicantState) intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE);
DetailedState state = WifiInfo.getDetailedStateOf(supplicantState);
Log.i(TAG, action + " " + WifiInfo.getDetailedStateOf(supplicantState) + " " + mConnected.get() + " "
+ SupplicantState.isHandshakeState(supplicantState) + " " + isHandshakeState(state));
// 本来源生是使用SupplicantState.isHandshakeState(supplicantState)来判断某一wifi连接状态的,
// 但是log显示它将DetailedState的DISCONNECTED状态过滤掉了,
// 故自己写了一个方法isHandshakeState(state)来判断是否过滤
// if (!mConnected.get() &&
// SupplicantState.isHandshakeState(supplicantState)) {
if (!mConnected.get() && isHandshakeState(state)) {
//wifi连接状态更新
updateConnectionState(WifiInfo.getDetailedStateOf(supplicantState));
}
int authState = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1);
if (authState == WifiManager.ERROR_AUTHENTICATING) {
updateAccessPoints();
}
}
// 网络的连接状态改变
else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
NetworkInfo info = (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
mConnected.set(info.isConnected());
// if (!(isEthprefer && processWifiEthBothOn()))
updateAccessPoints();
Log.i(TAG, action + " " + info.getDetailedState());
updateConnectionState(info.getDetailedState());
} else if (WifiManager.RSSI_CHANGED_ACTION.equals(action)) {
updateConnectionState(null);
}
}
private static boolean isHandshakeState(DetailedState state) {
return state != DetailedState.IDLE && state != DetailedState.SCANNING;
}
//此方法是获取wifi列表
/** Returns sorted list of access points */
private List<AccessPoint> constructAccessPoints() {
ArrayList<AccessPoint> accessPoints = new ArrayList<AccessPoint>();
/**
* Lookup table to more quickly update AccessPoints by only considering
* objects with the correct SSID. Maps SSID -> List of AccessPoints with
* the given SSID.
*/
Multimap<String, AccessPoint> apMap = new Multimap<String, AccessPoint>();
//
final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
if (configs != null) {
for (WifiConfiguration config : configs) {
AccessPoint accessPoint = new AccessPoint(config);
accessPoint.update(mLastInfo, mLastState);
accessPoints.add(accessPoint);
apMap.put(accessPoint.ssid, accessPoint);
}
}
final List<ScanResult> results = mWifiManager.getScanResults();
if (results != null) {
for (ScanResult result : results) {
// Ignore hidden and ad-hoc networks.
// [WPA-EAP-TKIP] : Ignore EAP WIFI.
//过滤ssid为空的wifi以及EAP加密网络
if (result.SSID == null || result.SSID.length() == 0 || result.capabilities.contains("[IBSS]")
|| result.capabilities.contains("[WPA-EAP-TKIP]")) {
continue;
}
boolean found = false;
for (AccessPoint accessPoint : apMap.getAll(result.SSID)) {
if (accessPoint.update(result))
found = true;
}
if (!found) {
AccessPoint accessPoint = new AccessPoint(result);
accessPoints.add(accessPoint);
apMap.put(accessPoint.ssid, accessPoint);
}
}
}
// Pre-sort accessPoints to speed preference insertion
Collections.sort(accessPoints);
return accessPoints;
}
已保存网络连接很简单,通过WifiConfiguration的networkId连接即可。
mWifiManager.connect(networkId, l);
根据wifi加密方式以及密码来创建WifiConfiguration对象(只有三种,EAP未写出来):
public WifiConfiguration getNewConfig(AccessPoint accessPoint, String password) {
if (accessPoint == null) {
return null;
}
if (TextUtils.isEmpty(password) && accessPoint.security != AccessPoint.SECURITY_NONE) {
return null;
}
if (accessPoint.networkId != WifiConfiguration.INVALID_NETWORK_ID) {
return null;
}
WifiConfiguration config = new WifiConfiguration();
config.SSID = AccessPoint.convertToQuotedString(accessPoint.ssid);
switch (accessPoint.security) {
case AccessPoint.SECURITY_NONE:
config.allowedKeyManagement.set(KeyMgmt.NONE);
break;
case AccessPoint.SECURITY_WEP:
config.allowedKeyManagement.set(KeyMgmt.NONE);
config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
int length = password.length();
// WEP-40, WEP-104, and 256-bit WEP (WEP-232?)
if ((length == 10 || length == 26 || length == 58) && password.matches("[0-9A-Fa-f]*")) {
config.wepKeys[0] = password;
} else {
config.wepKeys[0] = '"' + password + '"';
}
break;
case AccessPoint.SECURITY_PSK:
config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
if (password.matches("[0-9A-Fa-f]{64}")) {
config.preSharedKey = password;
} else {
config.preSharedKey = '"' + password + '"';
}
break;
default:
return null;
}
return config;
}
(2)WEP加密网络的使用:测试时一直连不上此种类型的网络,是路由器WEP加密网络设置错误,将密码设置后,会生成十位长度的密钥1,此为密码。
下次介绍wifi网络的自动配置以及设置静态ip。