1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.wifi; 18 19 import android.app.Activity; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.pm.ActivityInfo; 23 import android.net.NetworkInfo.DetailedState; 24 import android.net.wifi.WifiConfiguration; 25 import android.net.wifi.WifiManager; 26 import android.os.Bundle; 27 import android.os.Handler; 28 import android.os.Message; 29 import android.preference.PreferenceScreen; 30 import android.text.TextUtils; 31 import android.util.Log; 32 import android.view.View; 33 import android.view.View.OnClickListener; 34 import android.view.ViewGroup; 35 import android.view.Window; 36 import android.view.inputmethod.InputMethodManager; 37 import android.widget.Button; 38 import android.widget.ProgressBar; 39 import android.widget.TextView; 40 41 import com.android.settings.R; 42 43 import java.util.Collection; 44 import java.util.EnumMap; 45 import java.util.List; 46 47 /** 48 * WifiSetings Activity specific for SetupWizard with X-Large screen size. 49 */ 50 public class WifiSettingsForSetupWizardXL extends Activity implements OnClickListener { 51 private static final String TAG = "SetupWizard"; 52 private static final boolean DEBUG = true; 53 54 // lock orientation into landscape or portrait 55 private static final String EXTRA_PREFS_LANDSCAPE_LOCK = "extra_prefs_landscape_lock"; 56 private static final String EXTRA_PREFS_PORTRAIT_LOCK = "extra_prefs_portrait_lock"; 57 58 private static final EnumMap<DetailedState, DetailedState> sNetworkStateMap = 59 new EnumMap<DetailedState, DetailedState>(DetailedState.class); 60 61 static { sNetworkStateMap.put(DetailedState.IDLE, DetailedState.DISCONNECTED)62 sNetworkStateMap.put(DetailedState.IDLE, DetailedState.DISCONNECTED); sNetworkStateMap.put(DetailedState.SCANNING, DetailedState.SCANNING)63 sNetworkStateMap.put(DetailedState.SCANNING, DetailedState.SCANNING); sNetworkStateMap.put(DetailedState.CONNECTING, DetailedState.CONNECTING)64 sNetworkStateMap.put(DetailedState.CONNECTING, DetailedState.CONNECTING); sNetworkStateMap.put(DetailedState.AUTHENTICATING, DetailedState.CONNECTING)65 sNetworkStateMap.put(DetailedState.AUTHENTICATING, DetailedState.CONNECTING); sNetworkStateMap.put(DetailedState.OBTAINING_IPADDR, DetailedState.CONNECTING)66 sNetworkStateMap.put(DetailedState.OBTAINING_IPADDR, DetailedState.CONNECTING); sNetworkStateMap.put(DetailedState.CONNECTED, DetailedState.CONNECTED)67 sNetworkStateMap.put(DetailedState.CONNECTED, DetailedState.CONNECTED); sNetworkStateMap.put(DetailedState.SUSPENDED, DetailedState.SUSPENDED)68 sNetworkStateMap.put(DetailedState.SUSPENDED, DetailedState.SUSPENDED); // ? sNetworkStateMap.put(DetailedState.DISCONNECTING, DetailedState.DISCONNECTED)69 sNetworkStateMap.put(DetailedState.DISCONNECTING, DetailedState.DISCONNECTED); sNetworkStateMap.put(DetailedState.DISCONNECTED, DetailedState.DISCONNECTED)70 sNetworkStateMap.put(DetailedState.DISCONNECTED, DetailedState.DISCONNECTED); sNetworkStateMap.put(DetailedState.FAILED, DetailedState.FAILED)71 sNetworkStateMap.put(DetailedState.FAILED, DetailedState.FAILED); 72 } 73 74 private WifiSettings mWifiSettings; 75 private WifiManager mWifiManager; 76 77 /** Used for resizing a padding above title. Hiden when software keyboard is shown. */ 78 private View mTopPadding; 79 80 /** Used for resizing a padding of main content. Hiden when software keyboard is shown. */ 81 private View mContentPadding; 82 83 private TextView mTitleView; 84 /** 85 * The name of a network currently connecting, or trying to connect. 86 * This may be empty ("") at first, and updated when configuration is changed. 87 */ 88 private CharSequence mNetworkName = ""; 89 private CharSequence mEditingTitle; 90 91 private ProgressBar mProgressBar; 92 private View mTopDividerNoProgress; 93 /** 94 * Used for resizing a padding between WifiSettings preference and bottom bar when 95 * ProgressBar is visible as a top divider. 96 */ 97 private View mBottomPadding; 98 99 private Button mAddNetworkButton; 100 private Button mRefreshButton; 101 private Button mSkipOrNextButton; 102 private Button mBackButton; 103 104 private Button mConnectButton; 105 106 /** 107 * View enclosing {@link WifiSettings}. 108 */ 109 private View mWifiSettingsFragmentLayout; 110 private View mConnectingStatusLayout; 111 private TextView mConnectingStatusView; 112 113 /* 114 * States of current screen, which should be saved and restored when Activity is relaunched 115 * with orientation change, etc. 116 */ 117 private static final int SCREEN_STATE_DISCONNECTED = 0; 118 private static final int SCREEN_STATE_EDITING = 1; 119 private static final int SCREEN_STATE_CONNECTING = 2; 120 private static final int SCREEN_STATE_CONNECTED = 3; 121 122 /** Current screen state. */ 123 private int mScreenState = SCREEN_STATE_DISCONNECTED; 124 125 private WifiConfigUiForSetupWizardXL mWifiConfig; 126 127 private InputMethodManager mInputMethodManager; 128 129 /** 130 * Previous network connection state reported by main Wifi module. 131 * 132 * Note that we don't use original {@link DetailedState} object but simplified one translated 133 * using sNetworkStateMap. 134 */ 135 private DetailedState mPreviousNetworkState = DetailedState.DISCONNECTED; 136 137 @Override onCreate(Bundle savedInstanceState)138 public void onCreate(Bundle savedInstanceState) { 139 super.onCreate(savedInstanceState); 140 requestWindowFeature(Window.FEATURE_NO_TITLE); 141 setContentView(R.layout.wifi_settings_for_setup_wizard_xl); 142 143 mWifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE); 144 // There's no button here enabling wifi network, so we need to enable it without 145 // users' request. 146 mWifiManager.setWifiEnabled(true); 147 148 mWifiSettings = 149 (WifiSettings)getFragmentManager().findFragmentById(R.id.wifi_setup_fragment); 150 mInputMethodManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); 151 152 initViews(); 153 154 // At first, Wifi module doesn't return SCANNING state (it's too early), so we manually 155 // show it. 156 showScanningState(); 157 } 158 initViews()159 private void initViews() { 160 Intent intent = getIntent(); 161 162 if (intent.getBooleanExtra("firstRun", false)) { 163 final View layoutRoot = findViewById(R.id.layout_root); 164 layoutRoot.setSystemUiVisibility(View.STATUS_BAR_DISABLE_BACK); 165 } 166 if (intent.getBooleanExtra(EXTRA_PREFS_LANDSCAPE_LOCK, false)) { 167 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE); 168 } 169 if (intent.getBooleanExtra(EXTRA_PREFS_PORTRAIT_LOCK, false)) { 170 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT); 171 } 172 173 mTitleView = (TextView)findViewById(R.id.wifi_setup_title); 174 mProgressBar = (ProgressBar)findViewById(R.id.scanning_progress_bar); 175 mProgressBar.setMax(2); 176 mTopDividerNoProgress = findViewById(R.id.top_divider_no_progress); 177 mBottomPadding = findViewById(R.id.bottom_padding); 178 179 mProgressBar.setVisibility(View.VISIBLE); 180 mProgressBar.setIndeterminate(true); 181 mTopDividerNoProgress.setVisibility(View.GONE); 182 183 mAddNetworkButton = (Button)findViewById(R.id.wifi_setup_add_network); 184 mAddNetworkButton.setOnClickListener(this); 185 mRefreshButton = (Button)findViewById(R.id.wifi_setup_refresh_list); 186 mRefreshButton.setOnClickListener(this); 187 mSkipOrNextButton = (Button)findViewById(R.id.wifi_setup_skip_or_next); 188 mSkipOrNextButton.setOnClickListener(this); 189 mConnectButton = (Button)findViewById(R.id.wifi_setup_connect); 190 mConnectButton.setOnClickListener(this); 191 mBackButton = (Button)findViewById(R.id.wifi_setup_cancel); 192 mBackButton.setOnClickListener(this); 193 194 mTopPadding = findViewById(R.id.top_padding); 195 mContentPadding = findViewById(R.id.content_padding); 196 197 mWifiSettingsFragmentLayout = findViewById(R.id.wifi_settings_fragment_layout); 198 mConnectingStatusLayout = findViewById(R.id.connecting_status_layout); 199 mConnectingStatusView = (TextView) findViewById(R.id.connecting_status); 200 } 201 restoreFirstVisibilityState()202 private void restoreFirstVisibilityState() { 203 showDefaultTitle(); 204 mAddNetworkButton.setVisibility(View.VISIBLE); 205 mRefreshButton.setVisibility(View.VISIBLE); 206 mSkipOrNextButton.setVisibility(View.VISIBLE); 207 mConnectButton.setVisibility(View.GONE); 208 mBackButton.setVisibility(View.GONE); 209 setPaddingVisibility(View.VISIBLE); 210 } 211 212 @Override onClick(View view)213 public void onClick(View view) { 214 hideSoftwareKeyboard(); 215 if (view == mAddNetworkButton) { 216 if (DEBUG) Log.d(TAG, "AddNetwork button pressed"); 217 onAddNetworkButtonPressed(); 218 } else if (view == mRefreshButton) { 219 if (DEBUG) Log.d(TAG, "Refresh button pressed"); 220 refreshAccessPoints(true); 221 } else if (view == mSkipOrNextButton) { 222 if (DEBUG) Log.d(TAG, "Skip/Next button pressed"); 223 if (TextUtils.equals(getString(R.string.wifi_setup_skip), ((Button)view).getText())) { 224 // We don't want to let Wifi enabled when a user press skip without choosing 225 // any access point. 226 mWifiManager.setWifiEnabled(false); 227 // Notify "skip" 228 setResult(RESULT_FIRST_USER); 229 } else { 230 setResult(RESULT_OK); 231 } 232 finish(); 233 } else if (view == mConnectButton) { 234 if (DEBUG) Log.d(TAG, "Connect button pressed"); 235 onConnectButtonPressed(); 236 } else if (view == mBackButton) { 237 if (DEBUG) Log.d(TAG, "Back button pressed"); 238 onBackButtonPressed(); 239 } 240 } 241 hideSoftwareKeyboard()242 private void hideSoftwareKeyboard() { 243 if (DEBUG) Log.i(TAG, "Hiding software keyboard."); 244 final View focusedView = getCurrentFocus(); 245 if (focusedView != null) { 246 mInputMethodManager.hideSoftInputFromWindow(focusedView.getWindowToken(), 0); 247 } 248 } 249 250 // Called from WifiSettings updateConnectionState(DetailedState originalState)251 /* package */ void updateConnectionState(DetailedState originalState) { 252 final DetailedState state = sNetworkStateMap.get(originalState); 253 254 if (originalState == DetailedState.FAILED) { 255 // We clean up the current connectivity status and let users select another network 256 // if they want. 257 refreshAccessPoints(true); 258 } 259 260 switch (state) { 261 case SCANNING: { 262 if (mScreenState == SCREEN_STATE_DISCONNECTED) { 263 if (mWifiSettings.getAccessPointsCount() == 0) { 264 showScanningState(); 265 } else { 266 showDisconnectedProgressBar(); 267 mWifiSettingsFragmentLayout.setVisibility(View.VISIBLE); 268 mBottomPadding.setVisibility(View.GONE); 269 } 270 } else { 271 showDisconnectedProgressBar(); 272 } 273 break; 274 } 275 case CONNECTING: { 276 if (mScreenState == SCREEN_STATE_CONNECTING) { 277 showConnectingState(); 278 } 279 break; 280 } 281 case CONNECTED: { 282 showConnectedState(); 283 break; 284 } 285 default: // DISCONNECTED, FAILED 286 if (mScreenState != SCREEN_STATE_CONNECTED && 287 mWifiSettings.getAccessPointsCount() > 0) { 288 showDisconnectedState(Summary.get(this, state, false /* isEphemeral */)); 289 } 290 break; 291 } 292 mPreviousNetworkState = state; 293 } 294 showDisconnectedState(String stateString)295 private void showDisconnectedState(String stateString) { 296 showDisconnectedProgressBar(); 297 if (mScreenState == SCREEN_STATE_DISCONNECTED && 298 mWifiSettings.getAccessPointsCount() > 0) { 299 mWifiSettingsFragmentLayout.setVisibility(View.VISIBLE); 300 mBottomPadding.setVisibility(View.GONE); 301 } 302 mAddNetworkButton.setEnabled(true); 303 mRefreshButton.setEnabled(true); 304 } 305 showConnectingState()306 private void showConnectingState() { 307 mScreenState = SCREEN_STATE_CONNECTING; 308 309 mBackButton.setVisibility(View.VISIBLE); 310 // We save this title and show it when authentication failed. 311 mEditingTitle = mTitleView.getText(); 312 showConnectingTitle(); 313 showConnectingProgressBar(); 314 315 setPaddingVisibility(View.VISIBLE); 316 } 317 showConnectedState()318 private void showConnectedState() { 319 // Once we show "connected" screen, we won't change it even when the device becomes 320 // disconnected afterwards. We keep the state unless a user explicitly cancel it 321 // (by pressing "back" button). 322 mScreenState = SCREEN_STATE_CONNECTED; 323 324 hideSoftwareKeyboard(); 325 setPaddingVisibility(View.VISIBLE); 326 327 showConnectedTitle(); 328 showConnectedProgressBar(); 329 330 mWifiSettingsFragmentLayout.setVisibility(View.GONE); 331 mConnectingStatusLayout.setVisibility(View.VISIBLE); 332 333 mConnectingStatusView.setText(R.string.wifi_setup_description_connected); 334 mConnectButton.setVisibility(View.GONE); 335 mAddNetworkButton.setVisibility(View.GONE); 336 mRefreshButton.setVisibility(View.GONE); 337 mBackButton.setVisibility(View.VISIBLE); 338 mBackButton.setText(R.string.wifi_setup_back); 339 mSkipOrNextButton.setVisibility(View.VISIBLE); 340 mSkipOrNextButton.setEnabled(true); 341 } 342 showDefaultTitle()343 private void showDefaultTitle() { 344 mTitleView.setText(getString(R.string.wifi_setup_title)); 345 } 346 showAddNetworkTitle()347 private void showAddNetworkTitle() { 348 mNetworkName = ""; 349 mTitleView.setText(R.string.wifi_setup_title_add_network); 350 } 351 showEditingTitle()352 private void showEditingTitle() { 353 if (TextUtils.isEmpty(mNetworkName) && mWifiConfig != null) { 354 if (mWifiConfig.getController() != null && 355 mWifiConfig.getController().getConfig() != null) { 356 mNetworkName = mWifiConfig.getController().getConfig().SSID; 357 } else { 358 Log.w(TAG, "Unexpected null found (WifiController or WifiConfig is null). " + 359 "Ignore them."); 360 } 361 } 362 mTitleView.setText(getString(R.string.wifi_setup_title_editing_network, mNetworkName)); 363 } 364 showConnectingTitle()365 private void showConnectingTitle() { 366 if (TextUtils.isEmpty(mNetworkName) && mWifiConfig != null) { 367 if (mWifiConfig.getController() != null && 368 mWifiConfig.getController().getConfig() != null) { 369 mNetworkName = mWifiConfig.getController().getConfig().SSID; 370 } else { 371 Log.w(TAG, "Unexpected null found (WifiController or WifiConfig is null). " + 372 "Ignore them."); 373 } 374 } 375 mTitleView.setText(getString(R.string.wifi_setup_title_connecting_network, mNetworkName)); 376 } 377 showConnectedTitle()378 private void showConnectedTitle() { 379 if (TextUtils.isEmpty(mNetworkName) && mWifiConfig != null) { 380 if (mWifiConfig.getController() != null && 381 mWifiConfig.getController().getConfig() != null) { 382 mNetworkName = mWifiConfig.getController().getConfig().SSID; 383 } else { 384 Log.w(TAG, "Unexpected null found (WifiController or WifiConfig is null). " + 385 "Ignore them."); 386 } 387 } 388 mTitleView.setText(getString(R.string.wifi_setup_title_connected_network, mNetworkName)); 389 } 390 391 /** 392 * Shows top divider with ProgressBar without defining the state of the ProgressBar. 393 * 394 * @see #showScanningProgressBar() 395 * @see #showConnectedProgressBar() 396 * @see #showConnectingProgressBar() 397 */ showTopDividerWithProgressBar()398 private void showTopDividerWithProgressBar() { 399 mProgressBar.setVisibility(View.VISIBLE); 400 mTopDividerNoProgress.setVisibility(View.GONE); 401 mBottomPadding.setVisibility(View.GONE); 402 } 403 showScanningState()404 private void showScanningState() { 405 setPaddingVisibility(View.VISIBLE); 406 mWifiSettingsFragmentLayout.setVisibility(View.GONE); 407 showScanningProgressBar(); 408 } 409 onAddNetworkButtonPressed()410 private void onAddNetworkButtonPressed() { 411 mWifiSettings.onAddNetworkPressed(); 412 } 413 414 /** 415 * Called when the screen enters wifi configuration UI. UI widget for configuring network 416 * (a.k.a. ConfigPreference) should be taken care of by caller side. 417 * This method should handle buttons' visibility/enabled. 418 * @param selectedAccessPoint AccessPoint object being selected. null when a user pressed 419 * "Add network" button, meaning there's no selected access point. 420 */ showConfigUi(AccessPoint selectedAccessPoint, boolean edit)421 /* package */ void showConfigUi(AccessPoint selectedAccessPoint, boolean edit) { 422 mScreenState = SCREEN_STATE_EDITING; 423 424 if (selectedAccessPoint != null && 425 (selectedAccessPoint.security == AccessPoint.SECURITY_WEP || 426 selectedAccessPoint.security == AccessPoint.SECURITY_PSK)) { 427 // We forcibly set edit as true so that users can modify every field if they want, 428 // while config UI doesn't allow them to edit some of them when edit is false 429 // (e.g. password field is hiden when edit==false). 430 edit = true; 431 } 432 433 // We don't want to keep scanning Wifi networks during users' configuring a network. 434 mWifiSettings.pauseWifiScan(); 435 436 mWifiSettingsFragmentLayout.setVisibility(View.GONE); 437 mConnectingStatusLayout.setVisibility(View.GONE); 438 final ViewGroup parent = (ViewGroup)findViewById(R.id.wifi_config_ui); 439 parent.setVisibility(View.VISIBLE); 440 parent.removeAllViews(); 441 mWifiConfig = new WifiConfigUiForSetupWizardXL(this, parent, selectedAccessPoint, edit); 442 443 if (selectedAccessPoint == null) { // "Add network" flow 444 showAddNetworkTitle(); 445 mConnectButton.setVisibility(View.VISIBLE); 446 447 showDisconnectedProgressBar(); 448 showEditingButtonState(); 449 } else if (selectedAccessPoint.security == AccessPoint.SECURITY_NONE) { 450 mNetworkName = selectedAccessPoint.getTitle().toString(); 451 452 // onConnectButtonPressed() will change visibility status. 453 mConnectButton.performClick(); 454 } else { 455 mNetworkName = selectedAccessPoint.getTitle().toString(); 456 showEditingTitle(); 457 showDisconnectedProgressBar(); 458 showEditingButtonState(); 459 if (selectedAccessPoint.security == AccessPoint.SECURITY_EAP) { 460 onEapNetworkSelected(); 461 } else { 462 mConnectButton.setVisibility(View.VISIBLE); 463 464 // WifiConfigController shows Connect button as "Save" when edit==true and a user 465 // tried to connect the network. 466 // In SetupWizard, we just show the button as "Connect" instead. 467 mConnectButton.setText(R.string.wifi_connect); 468 mBackButton.setText(R.string.wifi_setup_cancel); 469 } 470 } 471 } 472 473 /** 474 * Called before security fields are correctly set by {@link WifiConfigController}. 475 * 476 * @param view security field view 477 * @param accessPointSecurity type of security. e.g. AccessPoint.SECURITY_NONE 478 * @return true when it is ok for the caller to init security fields. false when 479 * all security fields are managed by this method, and thus the caller shouldn't touch them. 480 */ initSecurityFields(View view, int accessPointSecurity)481 /* package */ boolean initSecurityFields(View view, int accessPointSecurity) { 482 // Reset all states tweaked below. 483 view.findViewById(R.id.eap_not_supported).setVisibility(View.GONE); 484 view.findViewById(R.id.eap_not_supported_for_add_network).setVisibility(View.GONE); 485 view.findViewById(R.id.ssid_text).setVisibility(View.VISIBLE); 486 view.findViewById(R.id.ssid_layout).setVisibility(View.VISIBLE); 487 488 if (accessPointSecurity == AccessPoint.SECURITY_EAP) { 489 setPaddingVisibility(View.VISIBLE); 490 hideSoftwareKeyboard(); 491 492 // In SetupWizard for XLarge screen, we don't have enough space for showing 493 // configurations needed for EAP. We instead disable the whole feature there and let 494 // users configure those networks after the setup. 495 if (view.findViewById(R.id.type_ssid).getVisibility() == View.VISIBLE) { 496 view.findViewById(R.id.eap_not_supported_for_add_network) 497 .setVisibility(View.VISIBLE); 498 } else { 499 view.findViewById(R.id.eap_not_supported).setVisibility(View.VISIBLE); 500 } 501 view.findViewById(R.id.security_fields).setVisibility(View.GONE); 502 view.findViewById(R.id.ssid_text).setVisibility(View.GONE); 503 view.findViewById(R.id.ssid_layout).setVisibility(View.GONE); 504 onEapNetworkSelected(); 505 506 // This method did init security fields by itself. The caller must not do it. 507 return false; 508 } 509 510 mConnectButton.setVisibility(View.VISIBLE); 511 setPaddingVisibility(View.GONE); 512 513 // In "add network" flow, we'll see multiple initSecurityFields() calls with different 514 // accessPointSecurity variable. We want to show software keyboard conditionally everytime 515 // when this method is called. 516 if (mWifiConfig != null) { 517 if (accessPointSecurity == AccessPoint.SECURITY_PSK || 518 accessPointSecurity == AccessPoint.SECURITY_WEP) { 519 mWifiConfig.requestFocusAndShowKeyboard(R.id.password); 520 } else { 521 mWifiConfig.requestFocusAndShowKeyboard(R.id.ssid); 522 } 523 } 524 525 // Let the caller init security fields. 526 return true; 527 } 528 onEapNetworkSelected()529 private void onEapNetworkSelected() { 530 mConnectButton.setVisibility(View.GONE); 531 mBackButton.setText(R.string.wifi_setup_back); 532 } 533 showEditingButtonState()534 private void showEditingButtonState() { 535 mSkipOrNextButton.setVisibility(View.GONE); 536 mAddNetworkButton.setVisibility(View.GONE); 537 mRefreshButton.setVisibility(View.GONE); 538 mBackButton.setVisibility(View.VISIBLE); 539 } 540 541 // May be called when user press "connect" button in WifiDialog onConnectButtonPressed()542 /* package */ void onConnectButtonPressed() { 543 mScreenState = SCREEN_STATE_CONNECTING; 544 545 mWifiSettings.submit(mWifiConfig.getController()); 546 547 // updateConnectionState() isn't called soon by the main Wifi module after the user's 548 // "connect" request, and the user still sees "not connected" message for a while, which 549 // looks strange for users though legitimate from the view of the module. 550 // 551 // We instead manually show "connecting" message before the system gets actual 552 // "connecting" message from Wifi module. 553 showConnectingState(); 554 555 // Might be better to delay showing this button. 556 mBackButton.setVisibility(View.VISIBLE); 557 mBackButton.setText(R.string.wifi_setup_back); 558 559 final ViewGroup parent = (ViewGroup)findViewById(R.id.wifi_config_ui); 560 parent.setVisibility(View.GONE); 561 mConnectingStatusLayout.setVisibility(View.VISIBLE); 562 mConnectingStatusView.setText(R.string.wifi_setup_description_connecting); 563 564 mSkipOrNextButton.setVisibility(View.VISIBLE); 565 mSkipOrNextButton.setEnabled(false); 566 mConnectButton.setVisibility(View.GONE); 567 mAddNetworkButton.setVisibility(View.GONE); 568 mRefreshButton.setVisibility(View.GONE); 569 } 570 onBackButtonPressed()571 private void onBackButtonPressed() { 572 573 if (mScreenState == SCREEN_STATE_CONNECTING || mScreenState == SCREEN_STATE_CONNECTED) { 574 if (DEBUG) Log.d(TAG, "Back button pressed after connect action."); 575 mScreenState = SCREEN_STATE_DISCONNECTED; 576 577 // When a user press "Back" button after pressing "Connect" button, we want to cancel 578 // the "Connect" request and refresh the whole Wifi status. 579 restoreFirstVisibilityState(); 580 581 mSkipOrNextButton.setEnabled(true); 582 changeNextButtonState(false); // Skip 583 584 // Wifi list becomes empty for a moment. We show "scanning" effect to a user so that 585 // he/she won't be astonished there. This stops once the scan finishes. 586 showScanningState(); 587 588 // Remembered networks may be re-used during SetupWizard, which confuse users. 589 // We force the module to forget them to reduce UX complexity 590 final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks(); 591 for (WifiConfiguration config : configs) { 592 if (DEBUG) { 593 Log.d(TAG, String.format("forgeting Wi-Fi network \"%s\" (id: %d)", 594 config.SSID, config.networkId)); 595 } 596 mWifiManager.forget(config.networkId, new WifiManager.ActionListener() { 597 public void onSuccess() { 598 } 599 public void onFailure(int reason) { 600 //TODO: Add failure UI 601 } 602 }); 603 } 604 605 mWifiSettingsFragmentLayout.setVisibility(View.GONE); 606 refreshAccessPoints(true); 607 } else { // During user's Wifi configuration. 608 mScreenState = SCREEN_STATE_DISCONNECTED; 609 mWifiSettings.resumeWifiScan(); 610 611 restoreFirstVisibilityState(); 612 613 mAddNetworkButton.setEnabled(true); 614 mRefreshButton.setEnabled(true); 615 mSkipOrNextButton.setEnabled(true); 616 showDisconnectedProgressBar(); 617 mWifiSettingsFragmentLayout.setVisibility(View.VISIBLE); 618 mBottomPadding.setVisibility(View.GONE); 619 } 620 621 setPaddingVisibility(View.VISIBLE); 622 mConnectingStatusLayout.setVisibility(View.GONE); 623 final ViewGroup parent = (ViewGroup)findViewById(R.id.wifi_config_ui); 624 parent.removeAllViews(); 625 parent.setVisibility(View.GONE); 626 mWifiConfig = null; 627 } 628 629 /** 630 * @param connected true when the device is connected to a specific network. 631 */ changeNextButtonState(boolean connected)632 /* package */ void changeNextButtonState(boolean connected) { 633 if (connected) { 634 mSkipOrNextButton.setText(R.string.wifi_setup_next); 635 } else { 636 mSkipOrNextButton.setText(R.string.wifi_setup_skip); 637 } 638 } 639 640 /** 641 * Called when the list of AccessPoints are modified and this Activity needs to refresh 642 * the list. 643 * @param preferenceScreen 644 */ onAccessPointsUpdated( PreferenceScreen preferenceScreen, Collection<AccessPoint> accessPoints)645 /* package */ void onAccessPointsUpdated( 646 PreferenceScreen preferenceScreen, Collection<AccessPoint> accessPoints) { 647 // If we already show some of access points but the bar still shows "scanning" state, it 648 // should be stopped. 649 if (mProgressBar.isIndeterminate() && accessPoints.size() > 0) { 650 showDisconnectedProgressBar(); 651 if (mScreenState == SCREEN_STATE_DISCONNECTED) { 652 mWifiSettingsFragmentLayout.setVisibility(View.VISIBLE); 653 mBottomPadding.setVisibility(View.GONE); 654 } 655 mAddNetworkButton.setEnabled(true); 656 mRefreshButton.setEnabled(true); 657 } 658 659 for (AccessPoint accessPoint : accessPoints) { 660 accessPoint.setLayoutResource(R.layout.custom_preference); 661 preferenceScreen.addPreference(accessPoint); 662 } 663 } 664 refreshAccessPoints(boolean disconnectNetwork)665 private void refreshAccessPoints(boolean disconnectNetwork) { 666 showScanningState(); 667 668 if (disconnectNetwork) { 669 mWifiManager.disconnect(); 670 } 671 672 mWifiSettings.refreshAccessPoints(); 673 } 674 675 /** 676 * Called when {@link WifiSettings} received 677 * {@link WifiManager#SUPPLICANT_STATE_CHANGED_ACTION}. 678 */ onSupplicantStateChanged(Intent intent)679 /* package */ void onSupplicantStateChanged(Intent intent) { 680 final int errorCode = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1); 681 if (errorCode == WifiManager.ERROR_AUTHENTICATING) { 682 Log.i(TAG, "Received authentication error event."); 683 onAuthenticationFailure(); 684 } 685 } 686 687 /** 688 * Called once when Authentication failed. 689 */ onAuthenticationFailure()690 private void onAuthenticationFailure() { 691 mScreenState = SCREEN_STATE_EDITING; 692 693 mSkipOrNextButton.setVisibility(View.GONE); 694 mConnectButton.setVisibility(View.VISIBLE); 695 mConnectButton.setEnabled(true); 696 697 if (!TextUtils.isEmpty(mEditingTitle)) { 698 mTitleView.setText(mEditingTitle); 699 } else { 700 Log.w(TAG, "Title during editing/adding a network was empty."); 701 showEditingTitle(); 702 } 703 704 final ViewGroup parent = (ViewGroup)findViewById(R.id.wifi_config_ui); 705 parent.setVisibility(View.VISIBLE); 706 mConnectingStatusLayout.setVisibility(View.GONE); 707 708 showDisconnectedProgressBar(); 709 setPaddingVisibility(View.GONE); 710 } 711 712 // Used by WifiConfigUiForSetupWizardXL setPaddingVisibility(int visibility)713 /* package */ void setPaddingVisibility(int visibility) { 714 mTopPadding.setVisibility(visibility); 715 mContentPadding.setVisibility(visibility); 716 } 717 showDisconnectedProgressBar()718 private void showDisconnectedProgressBar() { 719 // The device may report DISCONNECTED during connecting to a network, at which we don't 720 // want to lose bottom padding of top divider implicitly added by ProgressBar. 721 if (mScreenState == SCREEN_STATE_DISCONNECTED) { 722 mProgressBar.setVisibility(View.GONE); 723 mProgressBar.setIndeterminate(false); 724 mTopDividerNoProgress.setVisibility(View.VISIBLE); 725 } else { 726 mProgressBar.setVisibility(View.VISIBLE); 727 mProgressBar.setIndeterminate(false); 728 mProgressBar.setProgress(0); 729 mTopDividerNoProgress.setVisibility(View.GONE); 730 } 731 } 732 733 /** 734 * Shows top divider with ProgressBar, whose state is intermediate. 735 */ showScanningProgressBar()736 private void showScanningProgressBar() { 737 showTopDividerWithProgressBar(); 738 mProgressBar.setIndeterminate(true); 739 } 740 741 /** 742 * Shows top divider with ProgressBar, showing "connecting" state. 743 */ showConnectingProgressBar()744 private void showConnectingProgressBar() { 745 showTopDividerWithProgressBar(); 746 mProgressBar.setIndeterminate(false); 747 mProgressBar.setProgress(1); 748 } 749 showConnectedProgressBar()750 private void showConnectedProgressBar() { 751 showTopDividerWithProgressBar(); 752 mProgressBar.setIndeterminate(false); 753 mProgressBar.setProgress(2); 754 } 755 756 /** 757 * Called when WifiManager is requested to save a network. 758 */ onSaveNetwork(WifiConfiguration config)759 /* package */ void onSaveNetwork(WifiConfiguration config) { 760 // We want to both save and connect a network. connectNetwork() does both. 761 mWifiManager.connect(config, new WifiManager.ActionListener() { 762 public void onSuccess() { 763 } 764 public void onFailure(int reason) { 765 //TODO: Add failure UI 766 } 767 }); 768 } 769 } 770