PS:基于Android P
首先在AndroidManifest.xml中定位WIfiSettings
android:value="com.android.settings.wifi.WifiSettings"
/packages/apps/settings/src/com/android/settings/wifi/...
此路径下为wifi应用层相关文件
我们找到WifiSettings.java分析代码
先看到wifi的开关
1. onStart()
// On/off switch is hidden for Setup Wizard (returns null) mWifiEnabler = createWifiEnabler(); if (mIsRestricted) { restrictUi(); return; } onWifiStateChanged(mWifiManager.getWifiState());
实现了一个WifiEnabler也就是Wifi开关功能
onWifiStateChanged判断wifi状态并执行不同的操作
/** Called when the state of Wifi has changed. */ @Override public void onWifiStateChanged(int state) { if (mIsRestricted) { return; } final int wifiState = mWifiManager.getWifiState(); switch (wifiState) { case WifiManager.WIFI_STATE_ENABLED: updateAccessPointPreferences(); break; case WifiManager.WIFI_STATE_ENABLING: removeConnectedAccessPointPreference(); mAccessPointsPreferenceCategory.removeAll(); addMessagePreference(R.string.wifi_starting); setProgressBarVisible(true); break; case WifiManager.WIFI_STATE_DISABLING: removeConnectedAccessPointPreference(); mAccessPointsPreferenceCategory.removeAll(); addMessagePreference(R.string.wifi_stopping); break; case WifiManager.WIFI_STATE_DISABLED: setOffMessage(); setAdditionalSettingsSummaries(); setProgressBarVisible(false); break; } }
createWifiEnabler() new 了一个WifiEnabler对象
/** * @return new WifiEnabler or null (as overridden by WifiSettingsForSetupWizard) */ private WifiEnabler createWifiEnabler() { final SettingsActivity activity = (SettingsActivity) getActivity(); return new WifiEnabler(activity, new SwitchBarController(activity.getSwitchBar()), mMetricsFeatureProvider); }
找到对应java文件
/packages/apps/Settings/src/com/android/settings/wifi/WifiEnabler.java
@Override public boolean onSwitchToggled(boolean isChecked) { //Do nothing if called as a result of a state machine event if (mStateMachineEvent) { return true; } // Show toast message if Wi-Fi is not allowed in airplane mode if (isChecked && !WirelessUtils.isRadioAllowed(mContext, Settings.Global.RADIO_WIFI)) { Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show(); // Reset switch to off. No infinite check/listener loop. mSwitchWidget.setChecked(false); return false; } if (isChecked) { mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_WIFI_ON); } else { // Log if user was connected at the time of switching off. mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_WIFI_OFF, mConnected.get()); } if (!mWifiManager.setWifiEnabled(isChecked)) { // Error mSwitchWidget.setEnabled(true); Toast.makeText(mContext, R.string.wifi_error, Toast.LENGTH_SHORT).show(); } return true; }
在onSwitchToggled方法中调用了WifiManager的setWifiEnabled()方法
WIfiManager属于框架层放到下一节
下面先看Wifi如何连接
在连接之前,先要扫面wifi得到周边的WiFi信息
WifiSettings->onWifiStateChanged()->case WifiManager.WIFI_STATE_ENABLED 执行updateAccessPointPreferences()方法
updateAccessPointPreferences()调用框架层的嗅探器获得可用接入点
// AccessPoints are sorted by the WifiTracker final ListaccessPoints = mWifiTracker.getAccessPoints();
得到list后遍历设置preference属性并添加进mAccessPointsPreferenceCategory
int numAccessPoints = accessPoints.size(); for (; index < numAccessPoints; index++) { AccessPoint accessPoint = accessPoints.get(index); // Ignore access points that are out of range. if (accessPoint.isReachable()) { String key = accessPoint.getKey(); hasAvailableAccessPoints = true; LongPressAccessPointPreference pref = (LongPressAccessPointPreference) getCachedPreference(key); if (pref != null) { pref.setOrder(index); continue; } LongPressAccessPointPreference preference = createLongPressAccessPointPreference(accessPoint); preference.setKey(key); preference.setOrder(index); if (mOpenSsid != null && mOpenSsid.equals(accessPoint.getSsidStr()) && accessPoint.getSecurity() != AccessPoint.SECURITY_NONE) { if (!accessPoint.isSaved() || isDisabledByWrongPassword(accessPoint)) { onPreferenceTreeClick(preference); mOpenSsid = null; } } mAccessPointsPreferenceCategory.addPreference(preference); accessPoint.setListener(WifiSettings.this); preference.refresh(); } }
mAccessPointsPreferenceCategory 在addPreference()方法中被设置到界面,addPreference()在onCreate()中调用
@Override public void onCreate(Bundle icicle) { super.onCreate(icicle); // TODO(b/37429702): Add animations and preference comparator back after initial screen is // loaded (ODR). setAnimationAllowed(false); addPreferences(); mIsRestricted = isUiRestricted(); } private void addPreferences() { addPreferencesFromResource(R.xml.wifi_settings); mConnectedAccessPointPreferenceCategory = (PreferenceCategory) findPreference(PREF_KEY_CONNECTED_ACCESS_POINTS); mAccessPointsPreferenceCategory = (PreferenceCategory) findPreference(PREF_KEY_ACCESS_POINTS);
...
...
显示之后点击弹出dialog输入密码然后开始连接网络
复写父类的方法onPreferenceTreeClick()
@Override public boolean onPreferenceTreeClick(Preference preference) { // If the preference has a fragment set, open that if (preference.getFragment() != null) { preference.setOnPreferenceClickListener(null); return super.onPreferenceTreeClick(preference); } if (preference instanceof LongPressAccessPointPreference) { mSelectedAccessPoint = ((LongPressAccessPointPreference) preference).getAccessPoint(); if (mSelectedAccessPoint == null) { return false; } if (mSelectedAccessPoint.isActive()) { return super.onPreferenceTreeClick(preference); } /** * Bypass dialog and connect to unsecured networks, or previously connected saved * networks, or Passpoint provided networks. */ WifiConfiguration config = mSelectedAccessPoint.getConfig(); if (mSelectedAccessPoint.getSecurity() == AccessPoint.SECURITY_NONE) { mSelectedAccessPoint.generateOpenNetworkConfig(); connect(mSelectedAccessPoint.getConfig(), mSelectedAccessPoint.isSaved()); } else if (mSelectedAccessPoint.isSaved() && config != null && config.getNetworkSelectionStatus() != null && config.getNetworkSelectionStatus().getHasEverConnected()) { connect(config, true /* isSavedNetwork */); } else if (mSelectedAccessPoint.isPasspoint()) { // Access point provided by an installed Passpoint provider, connect using // the associated config. connect(config, true /* isSavedNetwork */); } else { showDialog(mSelectedAccessPoint, WifiConfigUiBase.MODE_CONNECT); } } else if (preference == mAddPreference) { onAddNetworkPressed(); } else { return super.onPreferenceTreeClick(preference); } return true; }
如果第一次进入wifi没有连接过网络应该走的是走
showDialog(mSelectedAccessPoint, WifiConfigUiBase.MODE_CONNECT);
private void showDialog(AccessPoint accessPoint, int dialogMode) { if (accessPoint != null) { WifiConfiguration config = accessPoint.getConfig(); if (WifiUtils.isNetworkLockedDown(getActivity(), config) && accessPoint.isActive()) { RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getActivity(), RestrictedLockUtils.getDeviceOwner(getActivity())); return; } } if (mDialog != null) { removeDialog(WIFI_DIALOG_ID); mDialog = null; } // Save the access point and edit mode mDlgAccessPoint = accessPoint; mDialogMode = dialogMode; showDialog(WIFI_DIALOG_ID); }
这里只做对象传递
实际操作在覆写的父类方法onCreateDialog()中
@Override public Dialog onCreateDialog(int dialogId) { switch (dialogId) { case WIFI_DIALOG_ID: if (mDlgAccessPoint == null && mAccessPointSavedState == null) { // add new network mDialog = WifiDialog .createFullscreen(getActivity(), this, mDlgAccessPoint, mDialogMode); } else { // modify network if (mDlgAccessPoint == null) { // restore AP from save state mDlgAccessPoint = new AccessPoint(getActivity(), mAccessPointSavedState); // Reset the saved access point data mAccessPointSavedState = null; } mDialog = WifiDialog .createModal(getActivity(), this, mDlgAccessPoint, mDialogMode); } mSelectedAccessPoint = mDlgAccessPoint; return mDialog;
....
....
弹出dialog输入密码后点击连接会调用onSubmit()方法
此方法覆写于父类
实际上调用submit()方法
@Override public void onSubmit(WifiDialog dialog) { if (mDialog != null) { submit(mDialog.getController()); } } /* package */ void submit(WifiConfigController configController) { final WifiConfiguration config = configController.getConfig(); if (config == null) { if (mSelectedAccessPoint != null && mSelectedAccessPoint.isSaved()) { connect(mSelectedAccessPoint.getConfig(), true /* isSavedNetwork */); } } else if (configController.getMode() == WifiConfigUiBase.MODE_MODIFY) { mWifiManager.save(config, mSaveListener); } else { mWifiManager.save(config, mSaveListener); if (mSelectedAccessPoint != null) { // Not an "Add network" connect(config, false /* isSavedNetwork */); } } mWifiTracker.resumeScanning(); }
判断处理后调用connect()方法连接wifi
protected void connect(final WifiConfiguration config, boolean isSavedNetwork) { // Log subtype if configuration is a saved network. mMetricsFeatureProvider.action(getVisibilityLogger(), MetricsEvent.ACTION_WIFI_CONNECT, isSavedNetwork); mWifiManager.connect(config, mConnectListener); mClickedConnect = true; } protected void connect(final int networkId, boolean isSavedNetwork) { // Log subtype if configuration is a saved network. mMetricsFeatureProvider.action(getActivity(), MetricsEvent.ACTION_WIFI_CONNECT, isSavedNetwork); mWifiManager.connect(networkId, mConnectListener); }
最终调用了框架层WifiManager的connect()方法
在wifi开关的流程中也是以该类结尾,可以发现WifiManager这个java类是wifi功能上层的一个核心类,下一节将具体分析该类及其他框架层相关。