Android WIFI 詳解
public booleanonOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_ID_SCAN:
if(mWifiManager.isWifiEnabled()) {
mScanner.resume();
}
return true;
case MENU_ID_ADVANCED:
startActivity(new Intent(this,AdvancedSettings.class));
return true;
}
return super.onOptionsItemSelected(item);
}
private class Scanner extends Handler {
private int mRetry = 0;
void resume() {
if (!hasMessages(0)) {
sendEmptyMessage(0);
}
}
void pause() {
mRetry = 0;
mAccessPoints.setProgress(false);
removeMessages(0);
}
@Override
public void handleMessage(Message message) {
if (mWifiManager.startScanActive()){
mRetry = 0;
} else if (++mRetry >= 3) {
mRetry = 0;
Toast.makeText(WifiSettings.this, R.string.wifi_fail_to_scan,
Toast.LENGTH_LONG).show();
return;
}
mAccessPoints.setProgress(mRetry != 0);
sendEmptyMessageDelayed(0, 6000);
}
}
這里的mWifiManager.startScanActive()就會(huì)調(diào)用WifiService里的startScan()函數(shù),下面的流程和上面的一樣,這里不贅述。
當(dāng)supplicant完成了這個(gè)掃描命令后,它會(huì)發(fā)送一個(gè)消息給上層,提醒他們掃描已經(jīng)完成,WifiMonitor會(huì)接收到這消息,然后再發(fā)送給WifiStateTracker。
Frameworks/base/wifi/java/android/net/wifi/WifiMonitor.java
void handleEvent(int event, String remainder) {
switch (event) {
caseDISCONNECTED:
handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED,remainder);
break;
case CONNECTED:
handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED,remainder);
break;
case SCAN_RESULTS:
mWifiStateTracker.notifyScanResultsAvailable();
break;
case UNKNOWN:
break;
}
}
WifiStateTracker將會(huì)廣播SCAN_RESULTS_AVAILABLE_ACTION消息:
Frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java
public voidhandleMessage(Message msg) {
Intent intent;
……
case EVENT_SCAN_RESULTS_AVAILABLE:
if(ActivityManagerNative.isSystemReady()) {
mContext.sendBroadcast(new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
}
sendScanResultsAvailable();
/**
* On receiving the first scanresults after connecting to
* the supplicant, switch scanmode over to passive.
*/
setScanMode(false);
break;
……
}
由于WifiSettings類注冊(cè)了intent,能夠處理SCAN_RESULTS_AVAILABLE_ACTION消息,它會(huì)調(diào)用handleEvent(),調(diào)用流程如下所示。
WifiSettings.handleEvent() =>WifiSettings.updateAccessPoints() => mWifiManager.getScanResults() => mService.getScanResults()=> mWifiStateTracker.scanResults() => WifiNative.scanResultsCommand()……
將獲取AP列表的命令發(fā)送到supplicant,然后supplicant通過(guò)Socket發(fā)送掃描結(jié)果,由上層接收并顯示。這和前面的消息獲取流程基本相同。
(3)配置,連接AP
當(dāng)用戶選擇一個(gè)活躍的AP時(shí),WifiSettings響應(yīng)打開(kāi)一個(gè)對(duì)話框來(lái)配置AP,比如加密方法和連接AP的驗(yàn)證模式。配置好AP后,WifiService添加或更新網(wǎng)絡(luò)連接到特定的AP。
packages/apps/settings/src/com/android/settings/wifi/WifiSetttings.java
public booleanonPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
if (preference instanceof AccessPoint) {
mSelected = (AccessPoint) preference;
showDialog(mSelected, false);
} else if (preference == mAddNetwork) {
mSelected = null;
showDialog(null, true);
} else if (preference == mNotifyOpenNetworks) {
Secure.putInt(getContentResolver(),
Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
mNotifyOpenNetworks.isChecked() ? 1 : 0);
} else {
return super.onPreferenceTreeClick(screen, preference);
}
return true;
}
配置好以后,當(dāng)按下“Connect Press”時(shí),WifiSettings通過(guò)發(fā)送LIST_NETWORK命令到supplicant來(lái)檢查該網(wǎng)絡(luò)是否配置。如果沒(méi)有該網(wǎng)絡(luò)或沒(méi)有配置 它,WifiService調(diào)用addorUpdateNetwork()函數(shù)來(lái)添加或更新網(wǎng)絡(luò),然后發(fā)送命令給supplicant,連接到這個(gè)網(wǎng)絡(luò)。 下面是從響應(yīng)連接按鈕到WifiService發(fā)送連接命令的代碼:
packages/apps/settings/src/com/android/settings/wifi/WifiSetttings.java
public void onClick(DialogInterfacedialogInterface, int button) {
if (button == WifiDialog.BUTTON_FORGET mSelected != null) {
forget(mSelected.networkId);
} else if (button == WifiDialog.BUTTON_SUBMIT mDialog !=null) {
WifiConfiguration config = mDialog.getConfig();
if (config == null) {
if (mSelected != null !requireKeyStore(mSelected.getConfig())) {
connect(mSelected.networkId);
}
} else if (config.networkId != -1) {
評(píng)論