首先看下它的继承链,WifiSettingsextendsRestrictedSettingsFragment,RestrictedSettingsFragmentextendsSettingsPreferenceFragment。SettingsPreferenceFragment也被很多App用在自己的设置页面。
继续看它的构造函数:
[代码]java代码:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
publicWifiSettings(){
super(DISALLOW_CONFIG_WIFI);
mFilter=newIntentFilter();
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=newBroadcastReceiver(){
@Override
publicvoidonReceive(Contextcontext,Intentintent){
handleEvent(intent);
}
};
mScanner=newScanner(this);
new了个BroadcastReceiver接收一系列广播。WIFI_STATE_CHANGED_ACTION事件当WIFI功能开启或关闭时会收到,SCAN_RESULTS_AVAILABLE_ACTION事件当手机扫描到有可用的WIFI连接时会收到,SUPPLICANT_STATE_CHANGED_ACTION事件当连接请求状态发生改变时会收到,NETWORK_STATE_CHANGED_ACTION事件当网络状态发生变化时会收到。BroadcastReceiver中使用handleEvent()来处理接收到的广播。
22
23
24
25
26
27
privatevoidhandleEvent(Intentintent){
Stringaction=intent.getAction();
if(WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)){
updateWifiState(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_UNKNOWN));
//WIFI功能开启或关闭或正在开启/正在关闭/未知
//则更新WIFI状态
}elseif(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action)||
WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION.equals(action)||
WifiManager.LINK_CONFIGURATION_CHANGED_ACTION.equals(action)){
updateAccessPoints();
//ScanResults有结果了或添加/更新/删除了一个网络或连接的网络配置改变(?)
//则更新APs
}elseif(WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)){
NetworkInfoinfo=(NetworkInfo)intent.getParcelableExtra(
WifiManager.EXTRA_NETWORK_INFO);
mConnected.set(info.isConnected());
changeNextButtonState(info.isConnected());
updateNetworkInfo(info);
//WIFI网络连接的变化
//
}elseif(WifiManager.RSSI_CHANGED_ACTION.equals(action)){
updateNetworkInfo(null);
//正在连接的WIFI信号强度变化
先来看updateAccessPoints()
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
privatevoidupdateAccessPoints(){
//Safeguardfromsomedelayedeventhandling
if(getActivity()==null)return;
if(isUiRestricted()){
//ezio:WTF
addMessagePreference(R.string.wifi_empty_list_user_restricted);
return;
finalintwifiState=mWifiManager.getWifiState();
//whenweupdatethescreen,checkifverboselogginghasbeenturnedonoroff
mVerboseLogging=mWifiManager.getVerboseLoggingLevel();
switch(wifiState){
caseWifiManager.WIFI_STATE_ENABLED:
//AccessPointsareautomaticallysortedwithTreeSet.
finalCollection
//ezio
constructAccessPoints(getActivity(),mWifiManager,mLastInfo,
mLastNetworkInfo);
getPreferenceScreen().removeAll();
if(accessPoints.size()==0){
//ezio:如果空,显示提示信息
addMessagePreference(R.string.wifi_empty_list_wifi_on);
for(AccessPointaccessPoint:accessPoints){
//Ignoreaccesspointsthatareoutofrange.
//ezio:如果accessPoints不为空,则弄一个PrefList装进去,忽略范围外的ap
if(accessPoint.getLevel()!=-1){
getPreferenceScreen().addPreference(accessPoint);
break;
caseWifiManager.WIFI_STATE_ENABLING:
caseWifiManager.WIFI_STATE_DISABLING:
addMessagePreference(R.string.wifi_stopping);
caseWifiManager.WIFI_STATE_DISABLED:
setOffMessage();
}
updateAccessPoints()当广播是WIFI已开启的时候,会构造APs,APs是放满AP的Collection。
找到constructAccessPoints()的实现,上方的注释已经给了我们提示,它能返回排序好的APs
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/**Returnssortedlistofaccesspoints*/
privatestaticList
WifiManagerwifiManager,WifiInfolastInfo,NetworkInfolastNetworkInfo){
ArrayList
/**LookuptabletomorequicklyupdateAccessPointsbyonlyconsideringobjectswiththe
*correctSSID.MapsSSID->ListofAccessPointswiththegivenSSID.*/
//multimap是Guava:GoogleCoreLibraries的api
Multimap
finalList
if(configs!=null){
//如果有configuredNetwork
//Update"SavedNetworks"menuoption.
if(savedNetworksExist!=(configs.size()>0)){
//如果savedNetworksExist为false,则反转
savedNetworksExist=!savedNetworksExist;
if(contextinstanceofActivity){
((Activity)context).invalidateOptionsMenu();
for(WifiConfigurationconfig:configs){
if(config.selfAdded&&config.numAssociation==0){
continue;
AccessPointaccessPoint=newAccessPoint(context,config);
if(lastInfo!=null&&lastNetworkInfo!=null){
accessPoint.update(lastInfo,lastNetworkInfo);
accessPoints.add(accessPoint);
apMap.put(accessPoint.ssid,accessPoint);
finalList
if(results!=null){
for(ScanResultresult:results){
//Ignorehiddenandad-hocnetworks.
if(result.SSID==null||result.SSID.length()==0||
result.capabilities.contains("[IBSS]")){
//continue:如果ssid==null或者length==0,则忽略这一个直接进行下一次for循环
booleanfound=false;
for(AccessPointaccessPoint:apMap.getAll(result.SSID)){
//ezio:apMap?
if(accessPoint.update(result))
found=true;
if(!found){
AccessPointaccessPoint=newAccessPoint(context,result);
//Pre-sortaccessPointstospeedpreferenceinsertion
Collections.sort(accessPoints);
returnaccessPoints;
}
其中用到了另一个类AccessPoint.java在包中找到AccessPoint.java类,它有三个构造函数:
AccessPoint(Contextcontext,WifiConfigurationconfig){
super(context);
loadConfig(config);
refresh();
AccessPoint(Contextcontext,ScanResultresult){
loadResult(result);
AccessPoint(Contextcontext,BundlesavedState){
mConfig=savedState.getParcelable(KEY_CONFIG);
if(mConfig!=null){
loadConfig(mConfig);
mScanResult=(ScanResult)savedState.getParcelable(KEY_SCANRESULT);
if(mScanResult!=null){
loadResult(mScanResult);
mInfo=(WifiInfo)savedState.getParcelable(KEY_WIFIINFO);
if(savedState.containsKey(KEY_NETWORKINFO)){
mNetworkInfo=savedState.getParcelable(KEY_NETWORKINFO);
update(mInfo,mNetworkInfo);
privatevoidloadConfig(WifiConfigurationconfig){
//如果SSID为null则将其赋值为空字符串,不为空则。。
ssid=(config.SSID==null"":removeDoubleQuotes(config.SSID));
bssid=config.BSSID;
security=getSecurity(config);
networkId=config.networkId;
mConfig=config;
privatevoidloadResult(ScanResultresult){
ssid=result.SSID;
bssid=result.BSSID;
security=getSecurity(result);
wpsAvailable=security!=SECURITY_EAP&&result.capabilities.contains("WPS");
if(security==SECURITY_PSK)
pskType=getPskType(result);
mRssi=result.level;
mScanResult=result;
if(result.seen>mSeen){
mSeen=result.seen;
AP类构造函数中调用loadConfig和loadResult两个函数来初始化成员变量,然后调用refresh来刷新。
接下来看用户点击WIFI会发生什么。在WifiSetting中找到
publicbooleanonPreferenceTreeClick(PreferenceScreenscreen,Preferencepreference){
if(preferenceinstanceofAccessPoint){
mSelectedAccessPoint=(AccessPoint)preference;
//bypass:绕过
/**Bypassdialogforunsecured,unsaved,andinactivenetworks*/
if(mSelectedAccessPoint.security==AccessPoint.SECURITY_NONE&&
mSelectedAccessPoint.networkId==INVALID_NETWORK_ID&&
!mSelectedAccessPoint.isActive()){
//生成一个不加密的WifiConfigration
mSelectedAccessPoint.generateOpenNetworkConfig();
if(!savedNetworksExist){
//如果不存在
savedNetworksExist=true;
//改为存在
getActivity().invalidateOptionsMenu();
//重新生成OptionsMenu
connect(mSelectedAccessPoint.getConfig());
}else{
showDialog(mSelectedAccessPoint,false);
returnsuper.onPreferenceTreeClick(screen,preference);
returntrue;
再追入AP中的generateOpenNetworkConfig
/**
*GenerateandsaveadefaultwifiConfigurationwithcommonvalues.
*Canonlybecalledforunsecurednetworks.
*@hide
*/
protectedvoidgenerateOpenNetworkConfig(){
if(security!=SECURITY_NONE)
thrownewIllegalStateException();
if(mConfig!=null)
mConfig=newWifiConfiguration();
mConfig.SSID=AccessPoint.convertToQuotedString(ssid);
mConfig.allowedKeyManagement.set(KeyMgmt.NONE);
会生成一个开放网络的Config接下来会调用connect连接选中的WIFI
1
2
3
4
5
6
7
protectedvoidconnect(finalWifiConfigurationconfig){
mWifiManager.connect(config,mConnectListener);
protectedvoidconnect(finalintnetworkId){
mWifiManager.connect(networkId,mConnectListener);
找到WifiManager中的connect方法,喜闻乐见的是hide方法,API中没有
*Connecttoanetworkwiththegivenconfiguration.Thenetworkalso
*getsaddedtothesupplicantconfiguration.
*
*Foranewnetwork,thisfunctionisusedinsteadofa
*sequenceofaddNetwork(),enableNetwork(),saveConfiguration()and
*reconnect()
*@paramconfigthesetofvariablesthatdescribetheconfiguration,
*containedina{@linkWifiConfiguration}object.
*@paramlistenerforcallbacksonsuccessorfailure.Canbenull.
*@throwsIllegalStateExceptioniftheWifiManagerinstanceneedstobe
*initializedagain
publicvoidconnect(WifiConfigurationconfig,ActionListenerlistener){
if(config==null)thrownewIllegalArgumentException("configcannotbenull");
validateChannel();
//UseINVALID_NETWORK_IDforarg1whenpassingaconfigobject
//arg1isusedtopassnetworkidwhenthenetworkalreadyexists
sAsyncChannel.sendMessage(CONNECT_NETWORK,WifiConfiguration.INVALID_NETWORK_ID,
putListener(listener),config);
*ConnecttoanetworkwiththegivennetworkId.
*ThisfunctionisusedinsteadofaenableNetwork(),saveConfiguration()and
*@paramnetworkIdthenetworkididentifiyingthenetworkinthe
*supplicantconfigurationlist
publicvoidconnect(intnetworkId,ActionListenerlistener){
if(networkId<0)thrownewIllegalArgumentException("Networkidcannotbenegative");
sAsyncChannel.sendMessage(CONNECT_NETWORK,networkId,putListener(listener));
然后回到WifiSettings中的onPreferenceTreeClick,如果不是开放网络,会调用showDialog()
privatevoidshowDialog(AccessPointaccessPoint,booleanedit){
if(mDialog!=null){
removeDialog(WIFI_DIALOG_ID);
mDialog=null;
//Savetheaccesspointandeditmode
mDlgAccessPoint=accessPoint;
mDlgEdit=edit;
showDialog(WIFI_DIALOG_ID);
最后一句调用了爷爷类的showDialog()
protectedvoidshowDialog(intdialogId){
if(mDialogFragment!=null){
Log.e(TAG,"Olddialogfragmentnotnull!");
mDialogFragment=newSettingsDialogFragment(this,dialogId);
mDialogFragment.show(getChildFragmentManager(),Integer.toString(dialogId));
SettingsDialogFragment是SettingsPreferenceFragment中的一个静态内部类,继承自DialogFragment
下方还有个onCreateDialog()
publicDialogonCreateDialog(intdialogId){
switch(dialogId){
caseWIFI_DIALOG_ID:
AccessPointap=mDlgAccessPoint;//Formanuallaunch
if(ap==null){//Forre-launchfromsavedstate
if(mAccessPointSavedState!=null){
ap=newAccessPoint(getActivity(),mAccessPointSavedState);
//Forrepeatedorientationchanges
mDlgAccessPoint=ap;
//Resetthesavedaccesspointdata
mAccessPointSavedState=null;
//Ifit'snull,fine,it'sforAddNetwork
mSelectedAccessPoint=ap;
mDialog=newWifiDialog(getActivity(),this,ap,mDlgEdit);
returnmDialog;
caseWPS_PBC_DIALOG_ID:
returnnewWpsDialog(getActivity(),WpsInfo.PBC);
caseWPS_PIN_DIALOG_ID:
returnnewWpsDialog(getActivity(),WpsInfo.DISPLAY);
caseWRITE_NFC_DIALOG_ID:
if(mSelectedAccessPoint!=null){
mWifiToNfcDialog=newWriteWifiConfigToNfcDialog(
getActivity(),mSelectedAccessPoint,mWifiManager);
returnmWifiToNfcDialog;
returnsuper.onCreateDialog(dialogId);
这回Google的攻城狮终于肯写点注释了,看起来顺了很多。想检查mDlgAccessPoint是否为null,如果null就从SavedState生成个新的ap,最后new一个WifiDialog,这个Dialog就是我们将要看到的Dialog。在包中找到WifiDialog.java,它有两个构造函数(带默认则是三个)
publicWifiDialog(Contextcontext,DialogInterface.OnClickListenerlistener,
AccessPointaccessPoint,booleanedit,booleanhideSubmitButton){
this(context,listener,accessPoint,edit);
mHideSubmitButton=hideSubmitButton;
AccessPointaccessPoint,booleanedit){
mEdit=edit;
mListener=listener;
mAccessPoint=accessPoint;
mHideSubmitButton=false;
可以看到之前调用的是4参数的,第二个参数是DialogInterface.OnClickListener,之前传入的this,那我们去WifiSettings中找到实现的接口的函数
publicvoidonClick(DialogInterfacedialogInterface,intbutton){
if(button==WifiDialog.BUTTON_FORGET&&mSelectedAccessPoint!=null){
forget();
}elseif(button==WifiDialog.BUTTON_SUBMIT){
submit(mDialog.getController());
很简单,判断了点击的是忘记网络还是连接WIFI。看下submit的代码
/*package*/voidsubmit(WifiConfigControllerconfigController){
finalWifiConfigurationconfig=configController.getConfig();
if(config==null){
if(mSelectedAccessPoint!=null
&&mSelectedAccessPoint.networkId!=INVALID_NETWORK_ID){