WiFi关闭状态下在SavedNetwork界面点击CONNECT按钮,WiFI会自动打开并连接,下面是代码流程(本文档主要分析Settings层的逻辑,Framework层主要会用到打开wifi和连接的API,这里不做分析):
android/packages/apps/Settings/res/values/strings.xml
Connect
android/packages/apps/Settings/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
在displayPreference 函数中加载 CONNECT 按钮,如果点击,则调用connectNetwork() 函数。
.setButton3Text(R.string.wifi_connect)
.setButton3Icon(R.drawable.ic_settings_wireless)
.setButton3OnClickListener(view -> connectNetwork())
connectNetwork 函数最后会调用updateConnectingState函数,根据Wifi打开状态,updateConnectingState会有不同的参数。当Wifi关闭时,参数为 STATE_ENABLE_WIFI 。
void connectNetwork() {
final Activity activity = mFragment.getActivity();
// error handling, connected/saved network should have mWifiConfig.
if (mWifiConfig == null) {
Toast.makeText(activity,
R.string.wifi_failed_connect_message,
Toast.LENGTH_SHORT).show();
return;
}
// init state before connect
mConnectingState = STATE_NONE;
if (mWifiManager.isWifiEnabled()) {
updateConnectingState(STATE_CONNECTING);
} else {
// Enable Wi-Fi automatically to connect AP
updateConnectingState(STATE_ENABLE_WIFI);
}
}
这里我们看 updateConnectingState 里对 STATE_ENABLE_WIFI 的处理:
首先是调用updateConnectedButton函数,也就是修改 CONNECT 这个button的状态,然后就是调用WifiManager的setWifiEnabled函数,也就是打开WIFI。
private void updateConnectingState(int state) {
final Activity activity = mFragment.getActivity();
Log.d(TAG, "updateConnectingState from " + mConnectingState + " to " + state);
switch (mConnectingState) {
case STATE_NONE:
case STATE_ENABLE_WIFI:
if (state == STATE_ENABLE_WIFI) {
Log.d(TAG, "Turn on Wi-Fi automatically!");
updateConnectedButton(STATE_ENABLE_WIFI);
Toast.makeText(activity,
R.string.wifi_turned_on_message,
Toast.LENGTH_SHORT).show();
mWifiManager.setWifiEnabled(true);
// start timer for error handling
startTimer();
}
}
private void updateConnectedButton(int state) {
switch (state) {
case STATE_ENABLE_WIFI:
case STATE_CONNECTING:
mButtonsPref.setButton3Text(R.string.wifi_connecting)
.setButton3Enabled(false);
break;
}
在WifiDetailPreferenceController中实现了一个WifiTracker的监听器,实时监听Wifi的状态,如果Wifi状态发生了改变,会进行相应处理。上面我们分析到WIfManager打开了WIfi,这时WifiTracker监听到,再次调用执行updateConnectingState函数,此时参数由第一次的STATE_ENABLE_WIFI变为STATE_CONNECTING。
final WifiTracker.WifiListener mWifiListener = new WifiTracker.WifiListener() {
/** Called when the state of Wifi has changed. */
public void onWifiStateChanged(int state) {
Log.d(TAG, "onWifiStateChanged(" + state + ")");
if (mConnectingState == STATE_ENABLE_WIFI && state == WifiManager.WIFI_STATE_ENABLED) {
updateConnectingState(STATE_CONNECTING);
} else if (mConnectingState != STATE_NONE && state == WifiManager.WIFI_STATE_DISABLED) {
// update as disconnected once Wi-Fi disabled since may not received
// onConnectedChanged for this case.
updateConnectingState(STATE_DISCONNECTED);
}
}
此时state 是 STATE_CONNECTING,调用 WifiManager 的connect 函数,connect的参数 mWifiConfig 为WifiDetailPreferenceController这个界面初始化时加载的AP,也就是我们所点开的这个SavedNetwork。
} else if (state == STATE_CONNECTING) {
Log.d(TAG, "connecting...");
updateConnectedButton(STATE_CONNECTING);
if (mAccessPoint.isPasspoint()) {
mWifiManager.connect(mWifiConfig, mConnectListener);
} else {
mWifiManager.connect(mWifiConfig.networkId, mConnectListener);
}
// start timer for error handling since framework didn't call back if failed
startTimer();
当连接成功以后,WifiTracker会再次监听到,此时会调用onConnectedChanged函数,执行refreshPage。
final WifiTracker.WifiListener mWifiListener = new WifiTracker.WifiListener() {
/** Called when the state of Wifi has changed. */
public void onWifiStateChanged(int state) {
Log.d(TAG, "onWifiStateChanged(" + state + ")");
/** Called when the connection state of wifi has changed. */
public void onConnectedChanged() {
refreshPage();
}
/**
* Called to indicate the list of AccessPoints has been updated and
* {@link WifiTracker#getAccessPoints()} should be called to get the updated list.
*/
public void onAccessPointsChanged() {
refreshPage();
}
};
refreshPage函数会执行updateAccessPoint函数,
private void refreshPage() {
if(!updateAccessPoint()) {
return;
}
看updateAccessPoint函数,连接状态发生改变,if语句成立,调用updateConnectingState,如果AP可用,updateConnectingState参数为STATE_CONNECTED,如果不可用,参数为STATE_DISCONNECTED。
boolean updateAccessPoint() {
if (mConnected != mAccessPoint.isActive()) {
mConnected = mAccessPoint.isActive();
changed = true;
updateConnectingState(mAccessPoint.isActive() ? STATE_CONNECTED : STATE_DISCONNECTED);
}
经过上面分析,此时updateConnectingState参数从STATE_CONNECTING变为STATE_CONNECTED(函数参数就是state),,再次修改CONNECT这个button的状态,然后刷新页面 refreshPage。
case STATE_CONNECTING:
if (state == STATE_CONNECTED) {
Log.d(TAG, "connected");
stopTimer();
updateConnectedButton(STATE_CONNECTED);
Toast.makeText(activity,
mContext.getString(R.string.wifi_connected_to_message,
mAccessPoint.getTitle()),
Toast.LENGTH_SHORT).show();
refreshPage();
到此Wifi从关闭到打开然后成功连接。