首页 > 代码库 > android4.1.1 Settings WIFI模块浅析

android4.1.1 Settings WIFI模块浅析

[java] view plaincopy

  1. <span style="font-family: Arial, Helvetica, sans-serif;">Settings 中的WIFI功能主要在package/Settings/src/com/android/wifi/WifiSettings实现</span>  

首先我们来看下WifiSettings类声明

[java] view plaincopy

  1. public class WifiSettings extends SettingsPreferenceFragment  

  2.         implements DialogInterface.OnClickListener  {  

  3.         ......  

  4. }  


继承SettingsPreferenceFragment,可见它是一个Fragment我们看到源码中的描述是这样的

/**
 * Two types of UI are provided here.
 *
 * The first is for "usual Settings", appearing as any other Setup fragment.
 *
 * The second is for Setup Wizard, with a simplified interface that hides the action bar
 * and menus.
 */

一、注册广播,接受相关wifi信息变化

 WifiSettins类主要负责监测wifi状态,以及加载各个连接点,并负责Fragment界面的显示。
 在WifiSettings类中比较重要的一个类是WifiManager(稍后再说,一步一步来).
 在WifiSettings构造函数中初始化一个BroadcastReceiver,该BroadcastReceiver监测外部广播

[java] view plaincopy

  1. public class WifiSettings extends SettingsPreferenceFragment  

  2.         implements DialogInterface.OnClickListener  {  

  3.         ......  

  4.          public WifiSettings() {  

  5.         mFilter = new IntentFilter();//添加过滤器  

  6.         mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);  

  7.         mFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);  

  8.         mFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);  

  9.         mFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);  

  10.         mFilter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);  

  11.         mFilter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);  

  12.         mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);  

  13.         mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);  

  14.   

  15.         mReceiver = new BroadcastReceiver() {  

  16.             @Override  

  17.             public void onReceive(Context context, Intent intent) {  

  18.                 handleEvent(context, intent);//事件处理函数  

  19.             }  

  20.         };  

  21.   

  22.         mScanner = new Scanner();  

  23.     }  

  24.     ......  

  25.     @Override  

  26.     public void onResume() {  

  27.         super.onResume();  

  28.         if (mWifiEnabler != null) {  

  29.             mWifiEnabler.resume();  

  30.         }  

  31.   

  32.         getActivity().registerReceiver(mReceiver, mFilter);//在onResume注册广播,获得相关wifi信息  

  33.         if (mKeyStoreNetworkId != INVALID_NETWORK_ID &&  

  34.                 KeyStore.getInstance().state() == KeyStore.State.UNLOCKED) {  

  35.             mWifiManager.connect(mChannel, mKeyStoreNetworkId, mConnectListener);  

  36.         }  

  37.         mKeyStoreNetworkId = INVALID_NETWORK_ID;  

  38.   

  39.         updateAccessPoints();  

  40.     }  

  41.     ......  

  42.      @Override  

  43.     public void onPause() {  

  44.         super.onPause();  

  45.         if (mWifiEnabler != null) {  

  46.             mWifiEnabler.pause();  

  47.         }  

  48.         getActivity().unregisterReceiver(mReceiver);//在onPause注销广播  

  49.         mScanner.pause();  

  50.     }  

  51.     ......  

  52. }  


广播的处理事件代码:

[java] view plaincopy

  1. private void handleEvent(Context context, Intent intent) {  

  2.         String action = intent.getAction();  

  3.         if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {  

  4.             updateWifiState(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,  

  5.                     WifiManager.WIFI_STATE_UNKNOWN));  

  6.         } else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action) ||  

  7.                 WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION.equals(action) ||  

  8.                 WifiManager.LINK_CONFIGURATION_CHANGED_ACTION.equals(action)) {  

  9.                 updateAccessPoints();  

  10.         } else if (WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(action)) {  

  11.             //Ignore supplicant state changes when network is connected  

  12.             //TODO: we should deprecate SUPPLICANT_STATE_CHANGED_ACTION and  

  13.             //introduce a broadcast that combines the supplicant and network  

  14.             //network state change events so the apps dont have to worry about  

  15.             //ignoring supplicant state change when network is connected  

  16.             //to get more fine grained information.  

  17.             SupplicantState state = (SupplicantState) intent.getParcelableExtra(  

  18.                     WifiManager.EXTRA_NEW_STATE);  

  19.             if (!mConnected.get() && SupplicantState.isHandshakeState(state)) {  

  20.                 updateConnectionState(WifiInfo.getDetailedStateOf(state));  

  21.             }  

  22.         } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {  

  23.             NetworkInfo info = (NetworkInfo) intent.getParcelableExtra(  

  24.                     WifiManager.EXTRA_NETWORK_INFO);  

  25.             mConnected.set(info.isConnected());  

  26.             changeNextButtonState(info.isConnected());  

  27.             updateAccessPoints();  

  28.             updateConnectionState(info.getDetailedState());  

  29.             if (mAutoFinishOnConnection && info.isConnected()) {  

  30.                 getActivity().finish();  

  31.                 return;  

  32.             }  

  33.         } else if (WifiManager.RSSI_CHANGED_ACTION.equals(action)) {  

  34.             updateConnectionState(null);  

  35.         }  

  36.     }  

二、WifiMananger类是是操作wifi的核心类

WifiManager定义wifi各种状态、wifi Action、网络配置等

[java] view plaincopy

  1. public class WifiManager {  

  2.    .....  

  3.  public WifiManager(IWifiManager service, Handler handler) {  

  4.         mService = service;  

  5.         mHandler = handler;  

  6.     }  

  7.    ......  

  8. }  

从IWifiManager 可知道,它是通过远程调用,也就是基于RPC原理(有时间再总结一下)。
为了保证Settings和Wifi相互交互,注册相应的监听对象。

[java] view plaincopy

  1. public class WifiSettings extends SettingsPreferenceFragment  

  2.         implements DialogInterface.OnClickListener  {  

  3.     ......  

  4.     private WifiManager.ActionListener mConnectListener;//连接  

  5.     private WifiManager.ActionListener mSaveListener;//保存  

  6.     private WifiManager.ActionListener mForgetListener;//清除保存  

  7.     ......  

  8.     //继承SettingsPreferenceFragment并从写 onActivityCreated方法  

  9.         @Override  

  10.     public void onActivityCreated(Bundle savedInstanceState) {  

  11.         // We don‘t call super.onActivityCreated() here, since it assumes we already set up  

  12.         // Preference (probably in onCreate()), while WifiSettings exceptionally set it up in  

  13.         // this method.  

  14.   

  15.         mP2pSupported = getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT);  

  16.         mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);  

  17.         mChannel = mWifiManager.initialize(getActivity(), getActivity().getMainLooper(), null);  

  18.   

  19.         mConnectListener = new WifiManager.ActionListener() {  

  20.                                    public void onSuccess() {//连接成功  

  21.                                    }  

  22.                                    public void onFailure(int reason) {//连接失败  

  23.                                         Toast.makeText(getActivity(),  

  24.                                             R.string.wifi_failed_connect_message,  

  25.                                             Toast.LENGTH_SHORT).show();  

  26.                                    }  

  27.                                };  

  28.   

  29.         mSaveListener = new WifiManager.ActionListener() {  

  30.                                 public void onSuccess() {//保存成功  

  31.                                 }  

  32.                                 public void onFailure(int reason) {//保存失败  

  33.                                     Toast.makeText(getActivity(),  

  34.                                         R.string.wifi_failed_save_message,  

  35.                                         Toast.LENGTH_SHORT).show();  

  36.                                 }  

  37.                             };  

  38.   

  39.         mForgetListener = new WifiManager.ActionListener() {  

  40.                                    public void onSuccess() {//清除保存成功  

  41.                                    }  

  42.                                    public void onFailure(int reason) {//清除保存失败  

  43.                                         Toast.makeText(getActivity(),  

  44.                                             R.string.wifi_failed_forget_message,  

  45.                                             Toast.LENGTH_SHORT).show();  

  46.                                    }  

  47.                                };  

  48.   

  49.         if (savedInstanceState != null  

  50.                 && savedInstanceState.containsKey(SAVE_DIALOG_ACCESS_POINT_STATE)) {  

  51.             mDlgEdit = savedInstanceState.getBoolean(SAVE_DIALOG_EDIT_MODE);  

  52.             mAccessPointSavedState = savedInstanceState.getBundle(SAVE_DIALOG_ACCESS_POINT_STATE);  

  53.         }  

  54.   

  55.         final Activity activity = getActivity();  

  56.         final Intent intent = activity.getIntent();  

  57.   

  58.         // first if we‘re supposed to finish once we have a connection  

  59.         mAutoFinishOnConnection = intent.getBooleanExtra(EXTRA_AUTO_FINISH_ON_CONNECT, false);  

  60.   

  61.         if (mAutoFinishOnConnection) {  

  62.             // Hide the next button  

  63.             if (hasNextButton()) {  

  64.                 getNextButton().setVisibility(View.GONE);  

  65.             }  

  66.   

  67.             final ConnectivityManager connectivity = (ConnectivityManager)  

  68.                     getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);  

  69.             if (connectivity != null  

  70.                     && connectivity.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected()) {  

  71.                 activity.finish();  

  72.                 return;  

  73.             }  

  74.         }  

  75.   

  76.         // if we‘re supposed to enable/disable the Next button based on our current connection  

  77.         // state, start it off in the right state  

  78.         mEnableNextOnConnection = intent.getBooleanExtra(EXTRA_ENABLE_NEXT_ON_CONNECT, false);  

  79.   

  80.         if (mEnableNextOnConnection) {  

  81.             if (hasNextButton()) {  

  82.                 final ConnectivityManager connectivity = (ConnectivityManager)  

  83.                         getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);  

  84.                 if (connectivity != null) {  

  85.                     NetworkInfo info = connectivity.getNetworkInfo(  

  86.                             ConnectivityManager.TYPE_WIFI);  

  87.                     changeNextButtonState(info.isConnected());  

  88.                 }  

  89.             }  

  90.         }  

  91.   

  92.         addPreferencesFromResource(R.xml.wifi_settings);//加载布局   

  93.   

  94.         if (mSetupWizardMode) {  

  95.             getView().setSystemUiVisibility(  

  96.                     View.STATUS_BAR_DISABLE_BACK |  

  97.                     View.STATUS_BAR_DISABLE_HOME |  

  98.                     View.STATUS_BAR_DISABLE_RECENT |  

  99.                     View.STATUS_BAR_DISABLE_NOTIFICATION_ALERTS |  

  100.                     View.STATUS_BAR_DISABLE_CLOCK);  

  101.         }  

  102.   

  103.         // On/off switch is hidden for Setup Wizard  

  104.         if (!mSetupWizardMode) {  

  105.             Switch actionBarSwitch = new Switch(activity);  

  106.   

  107.             if (activity instanceof PreferenceActivity) {  

  108.                 PreferenceActivity preferenceActivity = (PreferenceActivity) activity;  

  109.                 if (preferenceActivity.onIsHidingHeaders() || !preferenceActivity.onIsMultiPane()) {  

  110.                     final int padding = activity.getResources().getDimensionPixelSize(  

  111.                             R.dimen.action_bar_switch_padding);  

  112.                     actionBarSwitch.setPadding(00, padding, 0);  

  113.                     activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,  

  114.                             ActionBar.DISPLAY_SHOW_CUSTOM);  

  115.                     activity.getActionBar().setCustomView(actionBarSwitch, new ActionBar.LayoutParams(  

  116.                             ActionBar.LayoutParams.WRAP_CONTENT,  

  117.                             ActionBar.LayoutParams.WRAP_CONTENT,  

  118.                             Gravity.CENTER_VERTICAL | Gravity.RIGHT));  

  119.                 }  

  120.             }  

  121.   

  122.             mWifiEnabler = new WifiEnabler(activity, actionBarSwitch);  

  123.         }  

  124.   

  125.         mEmptyView = (TextView) getView().findViewById(android.R.id.empty);  

  126.         getListView().setEmptyView(mEmptyView);  

  127.   

  128.         if (!mSetupWizardMode) {  

  129.             registerForContextMenu(getListView());  

  130.         }  

  131.         setHasOptionsMenu(true);  

  132.   

  133.         // After confirming PreferenceScreen is available, we call super.  

  134.         super.onActivityCreated(savedInstanceState);  

  135.     }  

  136.     ......  

  137. }  


三、用户on/off交互
用户通过Switch 开关按钮进行对wifi打开和关闭

[java] view plaincopy

  1. public class WifiSettings extends SettingsPreferenceFragment  

  2.         implements DialogInterface.OnClickListener  {  

  3.         ......  

  4.       public void onActivityCreated(Bundle savedInstanceState) {  

  5.       ......  

  6.         // On/off switch is hidden for Setup Wizard  

  7.         if (!mSetupWizardMode) {  

  8.             Switch actionBarSwitch = new Switch(activity);  

  9.   

  10.             if (activity instanceof PreferenceActivity) {  

  11.                 PreferenceActivity preferenceActivity = (PreferenceActivity) activity;  

  12.                 if (preferenceActivity.onIsHidingHeaders() || !preferenceActivity.onIsMultiPane()) {  

  13.                     final int padding = activity.getResources().getDimensionPixelSize(  

  14.                             R.dimen.action_bar_switch_padding);  

  15.                     actionBarSwitch.setPadding(00, padding, 0);  

  16.                     activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,  

  17.                             ActionBar.DISPLAY_SHOW_CUSTOM);  

  18.                     activity.getActionBar().setCustomView(actionBarSwitch, new ActionBar.LayoutParams(  

  19.                             ActionBar.LayoutParams.WRAP_CONTENT,  

  20.                             ActionBar.LayoutParams.WRAP_CONTENT,  

  21.                             Gravity.CENTER_VERTICAL | Gravity.RIGHT));  

  22.                 }  

  23.             }  

  24.   

  25.             mWifiEnabler = new WifiEnabler(activity, actionBarSwitch);//将actionBarSwitch传递给WifiEnabler  

  26.         }  

  27.         ......  

  28.       }  

  29.       ......  

  30. }  

WifiEnabler接受一个Switch对象和,并该对象进行操作
我们可以看下WifiEnabler这个类

[java] view plaincopy

  1. import android.content.BroadcastReceiver;  

  2. import android.content.Context;  

  3. import android.content.Intent;  

  4. import android.content.IntentFilter;  

  5. import android.net.NetworkInfo;  

  6. import android.net.wifi.SupplicantState;  

  7. import android.net.wifi.WifiInfo;  

  8. import android.net.wifi.WifiManager;  

  9. import android.provider.Settings;  

  10. import android.widget.CompoundButton;  

  11. import android.widget.Switch;  

  12. import android.widget.Toast;  

  13.   

  14. import com.android.settings.R;  

  15. import com.android.settings.WirelessSettings;  

  16.   

  17. import java.util.concurrent.atomic.AtomicBoolean;  

  18.   

  19. public class WifiEnabler implements CompoundButton.OnCheckedChangeListener  {  

  20.     private final Context mContext;  

  21.     private Switch mSwitch;  

  22.     private AtomicBoolean mConnected = new AtomicBoolean(false);  

  23.   

  24.     private final WifiManager mWifiManager;  

  25.     private boolean mStateMachineEvent;  

  26.     private final IntentFilter mIntentFilter;  

  27.     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {  

  28.         @Override  

  29.         public void onReceive(Context context, Intent intent) {  

  30.             String action = intent.getAction();  

  31.             if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {  

  32.                 handleWifiStateChanged(intent.getIntExtra(  

  33.                         WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN));  

  34.             } else if (WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(action)) {  

  35.                 if (!mConnected.get()) {  

  36.                     handleStateChanged(WifiInfo.getDetailedStateOf((SupplicantState)  

  37.                             intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE)));  

  38.                 }  

  39.             } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {  

  40.                 NetworkInfo info = (NetworkInfo) intent.getParcelableExtra(  

  41.                         WifiManager.EXTRA_NETWORK_INFO);  

  42.                 mConnected.set(info.isConnected());  

  43.                 handleStateChanged(info.getDetailedState());  

  44.             }  

  45.         }  

  46.     };  

  47.   

  48.     public WifiEnabler(Context context, Switch switch_) {  

  49.         mContext = context;  

  50.         mSwitch = switch_;  

  51.   

  52.         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);  

  53.         mIntentFilter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);  

  54.         // The order matters! We really should not depend on this. :(  

  55.         mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);  

  56.         mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);  

  57.     }  

  58.   

  59.     public void resume() {  

  60.         // Wi-Fi state is sticky, so just let the receiver update UI  

  61.         mContext.registerReceiver(mReceiver, mIntentFilter);  

  62.         mSwitch.setOnCheckedChangeListener(this);  

  63.     }  

  64.   

  65.     public void pause() {  

  66.         mContext.unregisterReceiver(mReceiver);  

  67.         mSwitch.setOnCheckedChangeListener(null);  

  68.     }  

  69.   

  70.     public void setSwitch(Switch switch_) {  

  71.         if (mSwitch == switch_) return;  

  72.         mSwitch.setOnCheckedChangeListener(null);  

  73.         mSwitch = switch_;  

  74.         mSwitch.setOnCheckedChangeListener(this);  

  75.   

  76.         final int wifiState = mWifiManager.getWifiState();  

  77.         boolean isEnabled = wifiState == WifiManager.WIFI_STATE_ENABLED;  

  78.         boolean isDisabled = wifiState == WifiManager.WIFI_STATE_DISABLED;  

  79.         mSwitch.setChecked(isEnabled);  

  80.         mSwitch.setEnabled(isEnabled || isDisabled);  

  81.     }  

  82.   

  83.     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {  

  84.         //Do nothing if called as a result of a state machine event  

  85.         if (mStateMachineEvent) {  

  86.             return;  

  87.         }  

  88.         // Show toast message if Wi-Fi is not allowed in airplane mode  

  89.         if (isChecked && !WirelessSettings.isRadioAllowed(mContext, Settings.System.RADIO_WIFI)) {  

  90.             Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();  

  91.             // Reset switch to off. No infinite check/listenenr loop.  

  92.             buttonView.setChecked(false);  

  93.         }  

  94.   

  95.         // Disable tethering if enabling Wifi  

  96.         int wifiApState = mWifiManager.getWifiApState();  

  97.         if (isChecked && ((wifiApState == WifiManager.WIFI_AP_STATE_ENABLING) ||  

  98.                 (wifiApState == WifiManager.WIFI_AP_STATE_ENABLED))) {  

  99.             mWifiManager.setWifiApEnabled(nullfalse);  

  100.         }  

  101.   

  102.         if (mWifiManager.setWifiEnabled(isChecked)) {  

  103.             // Intent has been taken into account, disable until new state is active  

  104.             mSwitch.setEnabled(false);  

  105.         } else {  

  106.             // Error  

  107.             Toast.makeText(mContext, R.string.wifi_error, Toast.LENGTH_SHORT).show();  

  108.         }  

  109.     }  

  110.   

  111.     private void handleWifiStateChanged(int state) {  

  112.         switch (state) {  

  113.             case WifiManager.WIFI_STATE_ENABLING:  

  114.                 mSwitch.setEnabled(false);  

  115.                 break;  

  116.             case WifiManager.WIFI_STATE_ENABLED:  

  117.                 setSwitchChecked(true);  

  118.                 mSwitch.setEnabled(true);  

  119.                 break;  

  120.             case WifiManager.WIFI_STATE_DISABLING:  

  121.                 mSwitch.setEnabled(false);  

  122.                 break;  

  123.             case WifiManager.WIFI_STATE_DISABLED:  

  124.                 setSwitchChecked(false);  

  125.                 mSwitch.setEnabled(true);  

  126.                 break;  

  127.             default:  

  128.                 setSwitchChecked(false);  

  129.                 mSwitch.setEnabled(true);  

  130.                 break;  

  131.         }  

  132.     }  

  133.   

  134.     private void setSwitchChecked(boolean checked) {  

  135.         if (checked != mSwitch.isChecked()) {  

  136.             mStateMachineEvent = true;  

  137.             mSwitch.setChecked(checked);  

  138.             mStateMachineEvent = false;  

  139.         }  

  140.     }  

  141.   

  142.     private void handleStateChanged(@SuppressWarnings("unused") NetworkInfo.DetailedState state) {  

  143.         // After the refactoring from a CheckBoxPreference to a Switch, this method is useless since  

  144.         // there is nowhere to display a summary.  

  145.         // This code is kept in case a future change re-introduces an associated text.  

  146.         /* 

  147.         // WifiInfo is valid if and only if Wi-Fi is enabled. 

  148.         // Here we use the state of the switch as an optimization. 

  149.         if (state != null && mSwitch.isChecked()) { 

  150.             WifiInfo info = mWifiManager.getConnectionInfo(); 

  151.             if (info != null) { 

  152.                 //setSummary(Summary.get(mContext, info.getSSID(), state)); 

  153.             } 

  154.         } 

  155.         */  

  156.     }  

  157. }  


WifiEnabler实现了CompoundButton.OnCheckedChangeListener接口类,可见它也是一个监听器,并且在构造函数中通过接受一个switch对象去观察switch状态。


android4.1.1 Settings WIFI模块浅析