WifiSettings.java revision 8a963babe2e36b7a41f77b8d2598c97658196e58
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 17package com.android.settings.wifi; 18 19import static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID; 20import static android.os.UserManager.DISALLOW_CONFIG_WIFI; 21import android.app.Activity; 22import android.app.Dialog; 23import android.content.Context; 24import android.content.DialogInterface; 25import android.content.Intent; 26import android.content.res.Resources; 27import android.content.res.TypedArray; 28import android.location.LocationManager; 29import android.net.ConnectivityManager; 30import android.net.NetworkInfo; 31import android.net.NetworkInfo.State; 32import android.net.wifi.WifiConfiguration; 33import android.net.wifi.WifiManager; 34import android.net.wifi.WpsInfo; 35import android.nfc.NfcAdapter; 36import android.os.Bundle; 37import android.preference.Preference; 38import android.preference.PreferenceScreen; 39import android.util.Log; 40import android.view.ContextMenu; 41import android.view.ContextMenu.ContextMenuInfo; 42import android.view.Menu; 43import android.view.MenuInflater; 44import android.view.MenuItem; 45import android.view.View; 46import android.widget.AdapterView.AdapterContextMenuInfo; 47import android.widget.TextView; 48import android.widget.Toast; 49 50import com.android.internal.logging.MetricsLogger; 51import com.android.settings.R; 52import com.android.settings.RestrictedSettingsFragment; 53import com.android.settings.SettingsActivity; 54import com.android.settings.search.BaseSearchIndexProvider; 55import com.android.settings.search.Indexable; 56import com.android.settings.search.SearchIndexableRaw; 57import com.android.settingslib.wifi.AccessPoint; 58import com.android.settingslib.wifi.AccessPoint.AccessPointListener; 59import com.android.settingslib.wifi.WifiTracker; 60 61import java.util.ArrayList; 62import java.util.Collection; 63import java.util.List; 64 65/** 66 * Two types of UI are provided here. 67 * 68 * The first is for "usual Settings", appearing as any other Setup fragment. 69 * 70 * The second is for Setup Wizard, with a simplified interface that hides the action bar 71 * and menus. 72 */ 73public class WifiSettings extends RestrictedSettingsFragment 74 implements DialogInterface.OnClickListener, Indexable, WifiTracker.WifiListener, 75 AccessPointListener { 76 77 private static final String TAG = "WifiSettings"; 78 79 /* package */ static final int MENU_ID_WPS_PBC = Menu.FIRST; 80 private static final int MENU_ID_WPS_PIN = Menu.FIRST + 1; 81 private static final int MENU_ID_SAVED_NETWORK = Menu.FIRST + 2; 82 /* package */ static final int MENU_ID_ADD_NETWORK = Menu.FIRST + 3; 83 private static final int MENU_ID_ADVANCED = Menu.FIRST + 4; 84 private static final int MENU_ID_SCAN = Menu.FIRST + 5; 85 private static final int MENU_ID_CONNECT = Menu.FIRST + 6; 86 private static final int MENU_ID_FORGET = Menu.FIRST + 7; 87 private static final int MENU_ID_MODIFY = Menu.FIRST + 8; 88 private static final int MENU_ID_WRITE_NFC = Menu.FIRST + 9; 89 private static final int MENU_ID_APPS = Menu.FIRST + 10; 90 91 public static final int WIFI_DIALOG_ID = 1; 92 /* package */ static final int WPS_PBC_DIALOG_ID = 2; 93 private static final int WPS_PIN_DIALOG_ID = 3; 94 private static final int WRITE_NFC_DIALOG_ID = 6; 95 96 // Instance state keys 97 private static final String SAVE_DIALOG_EDIT_MODE = "edit_mode"; 98 private static final String SAVE_DIALOG_ACCESS_POINT_STATE = "wifi_ap_state"; 99 100 private static boolean savedNetworksExist; 101 102 protected WifiManager mWifiManager; 103 private WifiManager.ActionListener mConnectListener; 104 private WifiManager.ActionListener mSaveListener; 105 private WifiManager.ActionListener mForgetListener; 106 107 private WifiEnabler mWifiEnabler; 108 // An access point being editted is stored here. 109 private AccessPoint mSelectedAccessPoint; 110 111 private WifiDialog mDialog; 112 private WriteWifiConfigToNfcDialog mWifiToNfcDialog; 113 114 private TextView mEmptyView; 115 116 private boolean showAppIcons = false; 117 private MenuItem showAppMenuItem = null; 118 119 // this boolean extra specifies whether to disable the Next button when not connected. Used by 120 // account creation outside of setup wizard. 121 private static final String EXTRA_ENABLE_NEXT_ON_CONNECT = "wifi_enable_next_on_connect"; 122 // This string extra specifies a network to open the connect dialog on, so the user can enter 123 // network credentials. This is used by quick settings for secured networks. 124 private static final String EXTRA_START_CONNECT_SSID = "wifi_start_connect_ssid"; 125 126 // should Next button only be enabled when we have a connection? 127 private boolean mEnableNextOnConnection; 128 129 // Save the dialog details 130 private boolean mDlgEdit; 131 private AccessPoint mDlgAccessPoint; 132 private Bundle mAccessPointSavedState; 133 134 private WifiTracker mWifiTracker; 135 136 /* End of "used in Wifi Setup context" */ 137 138 public WifiSettings() { 139 super(DISALLOW_CONFIG_WIFI); 140 } 141 142 @Override 143 public void onActivityCreated(Bundle savedInstanceState) { 144 super.onActivityCreated(savedInstanceState); 145 146 mWifiTracker = new WifiTracker(getActivity(), this, true, true); 147 mWifiManager = mWifiTracker.getManager(); 148 149 mConnectListener = new WifiManager.ActionListener() { 150 @Override 151 public void onSuccess() { 152 } 153 @Override 154 public void onFailure(int reason) { 155 Activity activity = getActivity(); 156 if (activity != null) { 157 Toast.makeText(activity, 158 R.string.wifi_failed_connect_message, 159 Toast.LENGTH_SHORT).show(); 160 } 161 } 162 }; 163 164 mSaveListener = new WifiManager.ActionListener() { 165 @Override 166 public void onSuccess() { 167 } 168 @Override 169 public void onFailure(int reason) { 170 Activity activity = getActivity(); 171 if (activity != null) { 172 Toast.makeText(activity, 173 R.string.wifi_failed_save_message, 174 Toast.LENGTH_SHORT).show(); 175 } 176 } 177 }; 178 179 mForgetListener = new WifiManager.ActionListener() { 180 @Override 181 public void onSuccess() { 182 } 183 @Override 184 public void onFailure(int reason) { 185 Activity activity = getActivity(); 186 if (activity != null) { 187 Toast.makeText(activity, 188 R.string.wifi_failed_forget_message, 189 Toast.LENGTH_SHORT).show(); 190 } 191 } 192 }; 193 194 if (savedInstanceState != null) { 195 mDlgEdit = savedInstanceState.getBoolean(SAVE_DIALOG_EDIT_MODE); 196 if (savedInstanceState.containsKey(SAVE_DIALOG_ACCESS_POINT_STATE)) { 197 mAccessPointSavedState = 198 savedInstanceState.getBundle(SAVE_DIALOG_ACCESS_POINT_STATE); 199 } 200 } 201 202 // if we're supposed to enable/disable the Next button based on our current connection 203 // state, start it off in the right state 204 Intent intent = getActivity().getIntent(); 205 mEnableNextOnConnection = intent.getBooleanExtra(EXTRA_ENABLE_NEXT_ON_CONNECT, false); 206 207 if (mEnableNextOnConnection) { 208 if (hasNextButton()) { 209 final ConnectivityManager connectivity = (ConnectivityManager) 210 getActivity().getSystemService(Context.CONNECTIVITY_SERVICE); 211 if (connectivity != null) { 212 NetworkInfo info = connectivity.getNetworkInfo( 213 ConnectivityManager.TYPE_WIFI); 214 changeNextButtonState(info.isConnected()); 215 } 216 } 217 } 218 219 addPreferencesFromResource(R.xml.wifi_settings); 220 221 mEmptyView = initEmptyView(); 222 registerForContextMenu(getListView()); 223 setHasOptionsMenu(true); 224 225 if (intent.hasExtra(EXTRA_START_CONNECT_SSID)) { 226 String ssid = intent.getStringExtra(EXTRA_START_CONNECT_SSID); 227 onAccessPointsChanged(); 228 PreferenceScreen preferenceScreen = getPreferenceScreen(); 229 for (int i = 0; i < preferenceScreen.getPreferenceCount(); i++) { 230 Preference preference = preferenceScreen.getPreference(i); 231 if (preference instanceof AccessPointPreference) { 232 AccessPoint accessPoint = ((AccessPointPreference) preference).getAccessPoint(); 233 if (ssid.equals(accessPoint.getSsid()) && !accessPoint.isSaved() 234 && accessPoint.getSecurity() != AccessPoint.SECURITY_NONE) { 235 onPreferenceTreeClick(preferenceScreen, preference); 236 break; 237 } 238 } 239 } 240 } 241 } 242 243 @Override 244 public void onDestroyView() { 245 super.onDestroyView(); 246 247 if (mWifiEnabler != null) { 248 mWifiEnabler.teardownSwitchBar(); 249 } 250 } 251 252 @Override 253 public void onStart() { 254 super.onStart(); 255 256 // On/off switch is hidden for Setup Wizard (returns null) 257 mWifiEnabler = createWifiEnabler(); 258 } 259 260 /** 261 * @return new WifiEnabler or null (as overridden by WifiSettingsForSetupWizard) 262 */ 263 /* package */ WifiEnabler createWifiEnabler() { 264 final SettingsActivity activity = (SettingsActivity) getActivity(); 265 return new WifiEnabler(activity, activity.getSwitchBar()); 266 } 267 268 @Override 269 public void onResume() { 270 final Activity activity = getActivity(); 271 super.onResume(); 272 if (mWifiEnabler != null) { 273 mWifiEnabler.resume(activity); 274 } 275 276 mWifiTracker.startTracking(); 277 } 278 279 @Override 280 public void onPause() { 281 super.onPause(); 282 if (mWifiEnabler != null) { 283 mWifiEnabler.pause(); 284 } 285 286 mWifiTracker.stopTracking(); 287 } 288 289 @Override 290 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 291 // If the user is not allowed to configure wifi, do not show the menu. 292 if (isUiRestricted()) return; 293 294 addOptionsMenuItems(menu); 295 super.onCreateOptionsMenu(menu, inflater); 296 } 297 298 /** 299 * @param menu 300 */ 301 void addOptionsMenuItems(Menu menu) { 302 final boolean wifiIsEnabled = mWifiTracker.isWifiEnabled(); 303 TypedArray ta = getActivity().getTheme().obtainStyledAttributes( 304 new int[] {R.attr.ic_menu_add, R.attr.ic_wps}); 305 menu.add(Menu.NONE, MENU_ID_ADD_NETWORK, 0, R.string.wifi_add_network) 306 .setIcon(ta.getDrawable(0)) 307 .setEnabled(wifiIsEnabled) 308 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); 309 if (savedNetworksExist) { 310 menu.add(Menu.NONE, MENU_ID_SAVED_NETWORK, 0, R.string.wifi_saved_access_points_label) 311 .setIcon(ta.getDrawable(0)) 312 .setEnabled(wifiIsEnabled) 313 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); 314 } 315 menu.add(Menu.NONE, MENU_ID_SCAN, 0, R.string.menu_stats_refresh) 316 .setEnabled(wifiIsEnabled) 317 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); 318 menu.add(Menu.NONE, MENU_ID_ADVANCED, 0, R.string.wifi_menu_advanced) 319 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); 320 showAppMenuItem = menu.add(Menu.NONE, MENU_ID_APPS, 0, R.string.wifi_menu_apps); 321 showAppMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); 322 ta.recycle(); 323 } 324 325 @Override 326 protected int getMetricsCategory() { 327 return MetricsLogger.WIFI; 328 } 329 330 @Override 331 public void onSaveInstanceState(Bundle outState) { 332 super.onSaveInstanceState(outState); 333 334 // If the dialog is showing, save its state. 335 if (mDialog != null && mDialog.isShowing()) { 336 outState.putBoolean(SAVE_DIALOG_EDIT_MODE, mDlgEdit); 337 if (mDlgAccessPoint != null) { 338 mAccessPointSavedState = new Bundle(); 339 mDlgAccessPoint.saveWifiState(mAccessPointSavedState); 340 outState.putBundle(SAVE_DIALOG_ACCESS_POINT_STATE, mAccessPointSavedState); 341 } 342 } 343 } 344 345 @Override 346 public boolean onOptionsItemSelected(MenuItem item) { 347 // If the user is not allowed to configure wifi, do not handle menu selections. 348 if (isUiRestricted()) return false; 349 350 switch (item.getItemId()) { 351 case MENU_ID_WPS_PBC: 352 showDialog(WPS_PBC_DIALOG_ID); 353 return true; 354 /* 355 case MENU_ID_P2P: 356 if (getActivity() instanceof SettingsActivity) { 357 ((SettingsActivity) getActivity()).startPreferencePanel( 358 WifiP2pSettings.class.getCanonicalName(), 359 null, 360 R.string.wifi_p2p_settings_title, null, 361 this, 0); 362 } else { 363 startFragment(this, WifiP2pSettings.class.getCanonicalName(), 364 R.string.wifi_p2p_settings_title, -1, null); 365 } 366 return true; 367 */ 368 case MENU_ID_WPS_PIN: 369 showDialog(WPS_PIN_DIALOG_ID); 370 return true; 371 case MENU_ID_SCAN: 372 mWifiTracker.forceScan(); 373 return true; 374 case MENU_ID_ADD_NETWORK: 375 if (mWifiTracker.isWifiEnabled()) { 376 onAddNetworkPressed(); 377 } 378 return true; 379 case MENU_ID_SAVED_NETWORK: 380 if (getActivity() instanceof SettingsActivity) { 381 ((SettingsActivity) getActivity()).startPreferencePanel( 382 SavedAccessPointsWifiSettings.class.getCanonicalName(), null, 383 R.string.wifi_saved_access_points_titlebar, null, this, 0); 384 } else { 385 startFragment(this, SavedAccessPointsWifiSettings.class.getCanonicalName(), 386 R.string.wifi_saved_access_points_titlebar, 387 -1 /* Do not request a result */, null); 388 } 389 return true; 390 case MENU_ID_ADVANCED: 391 if (getActivity() instanceof SettingsActivity) { 392 ((SettingsActivity) getActivity()).startPreferencePanel( 393 AdvancedWifiSettings.class.getCanonicalName(), null, 394 R.string.wifi_advanced_titlebar, null, this, 0); 395 } else { 396 startFragment(this, AdvancedWifiSettings.class.getCanonicalName(), 397 R.string.wifi_advanced_titlebar, -1 /* Do not request a results */, 398 null); 399 } 400 return true; 401 case MENU_ID_APPS: 402 showAppIcons = !showAppIcons; 403 404 if (showAppIcons) { 405 showAppMenuItem.setTitle(R.string.wifi_menu_apps_strength); 406 } else { 407 showAppMenuItem.setTitle(R.string.wifi_menu_apps); 408 } 409 onAccessPointsChanged(); 410 return true; 411 } 412 return super.onOptionsItemSelected(item); 413 } 414 415 @Override 416 public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo info) { 417 if (info instanceof AdapterContextMenuInfo) { 418 Preference preference = (Preference) getListView().getItemAtPosition( 419 ((AdapterContextMenuInfo) info).position); 420 421 if (preference instanceof AccessPointPreference) { 422 mSelectedAccessPoint = ((AccessPointPreference) preference).getAccessPoint(); 423 menu.setHeaderTitle(mSelectedAccessPoint.getSsid()); 424 if (mSelectedAccessPoint.isConnectable()) { 425 menu.add(Menu.NONE, MENU_ID_CONNECT, 0, R.string.wifi_menu_connect); 426 } 427 428 if (mSelectedAccessPoint.isSaved() || mSelectedAccessPoint.isEphemeral()) { 429 // Allow forgetting a network if either the network is saved or ephemerally 430 // connected. (In the latter case, "forget" blacklists the network so it won't 431 // be used again, ephemerally). 432 menu.add(Menu.NONE, MENU_ID_FORGET, 0, R.string.wifi_menu_forget); 433 } 434 if (mSelectedAccessPoint.isSaved()) { 435 menu.add(Menu.NONE, MENU_ID_MODIFY, 0, R.string.wifi_menu_modify); 436 NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(getActivity()); 437 if (nfcAdapter != null && nfcAdapter.isEnabled() && 438 mSelectedAccessPoint.getSecurity() != AccessPoint.SECURITY_NONE) { 439 // Only allow writing of NFC tags for password-protected networks. 440 menu.add(Menu.NONE, MENU_ID_WRITE_NFC, 0, R.string.wifi_menu_write_to_nfc); 441 } 442 } 443 } 444 } 445 } 446 447 @Override 448 public boolean onContextItemSelected(MenuItem item) { 449 if (mSelectedAccessPoint == null) { 450 return super.onContextItemSelected(item); 451 } 452 switch (item.getItemId()) { 453 case MENU_ID_CONNECT: { 454 if (mSelectedAccessPoint.isSaved()) { 455 connect(mSelectedAccessPoint.getConfig()); 456 } else if (mSelectedAccessPoint.getSecurity() == AccessPoint.SECURITY_NONE) { 457 /** Bypass dialog for unsecured networks */ 458 mSelectedAccessPoint.generateOpenNetworkConfig(); 459 connect(mSelectedAccessPoint.getConfig()); 460 } else { 461 showDialog(mSelectedAccessPoint, true); 462 } 463 return true; 464 } 465 case MENU_ID_FORGET: { 466 forget(); 467 return true; 468 } 469 case MENU_ID_MODIFY: { 470 showDialog(mSelectedAccessPoint, true); 471 return true; 472 } 473 case MENU_ID_WRITE_NFC: 474 showDialog(WRITE_NFC_DIALOG_ID); 475 return true; 476 477 } 478 return super.onContextItemSelected(item); 479 } 480 481 @Override 482 public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) { 483 if (preference instanceof AccessPointPreference) { 484 mSelectedAccessPoint = ((AccessPointPreference) preference).getAccessPoint(); 485 /** Bypass dialog for unsecured, unsaved, and inactive networks */ 486 if (mSelectedAccessPoint.getSecurity() == AccessPoint.SECURITY_NONE && 487 !mSelectedAccessPoint.isSaved() && !mSelectedAccessPoint.isActive()) { 488 mSelectedAccessPoint.generateOpenNetworkConfig(); 489 if (!savedNetworksExist) { 490 savedNetworksExist = true; 491 getActivity().invalidateOptionsMenu(); 492 } 493 connect(mSelectedAccessPoint.getConfig()); 494 } else { 495 showDialog(mSelectedAccessPoint, false); 496 } 497 } else { 498 return super.onPreferenceTreeClick(screen, preference); 499 } 500 return true; 501 } 502 503 private void showDialog(AccessPoint accessPoint, boolean edit) { 504 if (mDialog != null) { 505 removeDialog(WIFI_DIALOG_ID); 506 mDialog = null; 507 } 508 509 // Save the access point and edit mode 510 mDlgAccessPoint = accessPoint; 511 mDlgEdit = edit; 512 513 showDialog(WIFI_DIALOG_ID); 514 } 515 516 @Override 517 public Dialog onCreateDialog(int dialogId) { 518 switch (dialogId) { 519 case WIFI_DIALOG_ID: 520 AccessPoint ap = mDlgAccessPoint; // For manual launch 521 if (ap == null) { // For re-launch from saved state 522 if (mAccessPointSavedState != null) { 523 ap = new AccessPoint(getActivity(), mAccessPointSavedState); 524 // For repeated orientation changes 525 mDlgAccessPoint = ap; 526 // Reset the saved access point data 527 mAccessPointSavedState = null; 528 } 529 } 530 // If it's null, fine, it's for Add Network 531 mSelectedAccessPoint = ap; 532 mDialog = new WifiDialog(getActivity(), this, ap, mDlgEdit); 533 return mDialog; 534 case WPS_PBC_DIALOG_ID: 535 return new WpsDialog(getActivity(), WpsInfo.PBC); 536 case WPS_PIN_DIALOG_ID: 537 return new WpsDialog(getActivity(), WpsInfo.DISPLAY); 538 case WRITE_NFC_DIALOG_ID: 539 if (mSelectedAccessPoint != null) { 540 mWifiToNfcDialog = new WriteWifiConfigToNfcDialog( 541 getActivity(), mSelectedAccessPoint, mWifiManager); 542 return mWifiToNfcDialog; 543 } 544 545 } 546 return super.onCreateDialog(dialogId); 547 } 548 549 /** 550 * Shows the latest access points available with supplemental information like 551 * the strength of network and the security for it. 552 */ 553 @Override 554 public void onAccessPointsChanged() { 555 // Safeguard from some delayed event handling 556 if (getActivity() == null) return; 557 558 if (isUiRestricted()) { 559 addMessagePreference(R.string.wifi_empty_list_user_restricted); 560 return; 561 } 562 final int wifiState = mWifiManager.getWifiState(); 563 564 switch (wifiState) { 565 case WifiManager.WIFI_STATE_ENABLED: 566 // AccessPoints are automatically sorted with TreeSet. 567 final Collection<AccessPoint> accessPoints = 568 mWifiTracker.getAccessPoints(); 569 getPreferenceScreen().removeAll(); 570 if (accessPoints.size() == 0) { 571 addMessagePreference(R.string.wifi_empty_list_wifi_on); 572 } 573 574 for (AccessPoint accessPoint : accessPoints) { 575 // Ignore access points that are out of range. 576 if (accessPoint.getLevel() != -1) { 577 AccessPointPreference preference = new AccessPointPreference(accessPoint, 578 getActivity()); 579 if (showAppIcons) { 580 preference.showAppIcon(); 581 } 582 583 getPreferenceScreen().addPreference(preference); 584 accessPoint.setListener(this); 585 } 586 } 587 break; 588 589 case WifiManager.WIFI_STATE_ENABLING: 590 getPreferenceScreen().removeAll(); 591 break; 592 593 case WifiManager.WIFI_STATE_DISABLING: 594 addMessagePreference(R.string.wifi_stopping); 595 break; 596 597 case WifiManager.WIFI_STATE_DISABLED: 598 setOffMessage(); 599 break; 600 } 601 // Update "Saved Networks" menu option. 602 if (savedNetworksExist != mWifiTracker.doSavedNetworksExist()) { 603 savedNetworksExist = !savedNetworksExist; 604 getActivity().invalidateOptionsMenu(); 605 } 606 } 607 608 protected TextView initEmptyView() { 609 TextView emptyView = (TextView) getActivity().findViewById(android.R.id.empty); 610 getListView().setEmptyView(emptyView); 611 return emptyView; 612 } 613 614 private void setOffMessage() { 615 if (mEmptyView != null) { 616 mEmptyView.setText(R.string.wifi_empty_list_wifi_off); 617 if (android.provider.Settings.Global.getInt(getActivity().getContentResolver(), 618 android.provider.Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 1) { 619 mEmptyView.append("\n\n"); 620 int resId; 621 if (android.provider.Settings.Secure.isLocationProviderEnabled( 622 getActivity().getContentResolver(), LocationManager.NETWORK_PROVIDER)) { 623 resId = R.string.wifi_scan_notify_text_location_on; 624 } else { 625 resId = R.string.wifi_scan_notify_text_location_off; 626 } 627 CharSequence charSeq = getText(resId); 628 mEmptyView.append(charSeq); 629 } 630 } 631 getPreferenceScreen().removeAll(); 632 } 633 634 private void addMessagePreference(int messageId) { 635 if (mEmptyView != null) mEmptyView.setText(messageId); 636 getPreferenceScreen().removeAll(); 637 } 638 639 @Override 640 public void onWifiStateChanged(int state) { 641 Activity activity = getActivity(); 642 if (activity != null) { 643 activity.invalidateOptionsMenu(); 644 } 645 646 switch (state) { 647 case WifiManager.WIFI_STATE_ENABLING: 648 addMessagePreference(R.string.wifi_starting); 649 break; 650 651 case WifiManager.WIFI_STATE_DISABLED: 652 setOffMessage(); 653 break; 654 } 655 } 656 657 @Override 658 public void onConnectedChanged() { 659 changeNextButtonState(mWifiTracker.isConnected()); 660 } 661 662 /** 663 * Renames/replaces "Next" button when appropriate. "Next" button usually exists in 664 * Wifi setup screens, not in usual wifi settings screen. 665 * 666 * @param enabled true when the device is connected to a wifi network. 667 */ 668 private void changeNextButtonState(boolean enabled) { 669 if (mEnableNextOnConnection && hasNextButton()) { 670 getNextButton().setEnabled(enabled); 671 } 672 } 673 674 @Override 675 public void onClick(DialogInterface dialogInterface, int button) { 676 if (button == WifiDialog.BUTTON_FORGET && mSelectedAccessPoint != null) { 677 forget(); 678 } else if (button == WifiDialog.BUTTON_SUBMIT) { 679 if (mDialog != null) { 680 submit(mDialog.getController()); 681 } 682 } 683 } 684 685 /* package */ void submit(WifiConfigController configController) { 686 687 final WifiConfiguration config = configController.getConfig(); 688 689 if (config == null) { 690 if (mSelectedAccessPoint != null 691 && mSelectedAccessPoint.isSaved()) { 692 connect(mSelectedAccessPoint.getConfig()); 693 } 694 } else if (config.networkId != INVALID_NETWORK_ID) { 695 if (mSelectedAccessPoint != null) { 696 mWifiManager.save(config, mSaveListener); 697 } 698 } else { 699 if (configController.isEdit()) { 700 mWifiManager.save(config, mSaveListener); 701 } else { 702 connect(config); 703 } 704 } 705 706 mWifiTracker.resumeScanning(); 707 } 708 709 /* package */ void forget() { 710 if (!mSelectedAccessPoint.isSaved()) { 711 if (mSelectedAccessPoint.getNetworkInfo().getState() != State.DISCONNECTED) { 712 // Network is active but has no network ID - must be ephemeral. 713 mWifiManager.disableEphemeralNetwork( 714 AccessPoint.convertToQuotedString(mSelectedAccessPoint.getSsid())); 715 } else { 716 // Should not happen, but a monkey seems to trigger it 717 Log.e(TAG, "Failed to forget invalid network " + mSelectedAccessPoint.getConfig()); 718 return; 719 } 720 } else { 721 mWifiManager.forget(mSelectedAccessPoint.getConfig().networkId, mForgetListener); 722 } 723 724 mWifiTracker.resumeScanning(); 725 726 // We need to rename/replace "Next" button in wifi setup context. 727 changeNextButtonState(false); 728 } 729 730 protected void connect(final WifiConfiguration config) { 731 mWifiManager.connect(config, mConnectListener); 732 } 733 734 protected void connect(final int networkId) { 735 mWifiManager.connect(networkId, mConnectListener); 736 } 737 738 /** 739 * Refreshes acccess points and ask Wifi module to scan networks again. 740 */ 741 /* package */ void refreshAccessPoints() { 742 mWifiTracker.resumeScanning(); 743 744 getPreferenceScreen().removeAll(); 745 } 746 747 /** 748 * Called when "add network" button is pressed. 749 */ 750 /* package */ void onAddNetworkPressed() { 751 // No exact access point is selected. 752 mSelectedAccessPoint = null; 753 showDialog(null, true); 754 } 755 756 /* package */ int getAccessPointsCount() { 757 final boolean wifiIsEnabled = mWifiTracker.isWifiEnabled(); 758 if (wifiIsEnabled) { 759 return getPreferenceScreen().getPreferenceCount(); 760 } else { 761 return 0; 762 } 763 } 764 765 /** 766 * Requests wifi module to pause wifi scan. May be ignored when the module is disabled. 767 */ 768 /* package */ void pauseWifiScan() { 769 mWifiTracker.pauseScanning(); 770 } 771 772 /** 773 * Requests wifi module to resume wifi scan. May be ignored when the module is disabled. 774 */ 775 /* package */ void resumeWifiScan() { 776 mWifiTracker.resumeScanning(); 777 } 778 779 @Override 780 protected int getHelpResource() { 781 return R.string.help_url_wifi; 782 } 783 784 @Override 785 public void onAccessPointChanged(AccessPoint accessPoint) { 786 ((AccessPointPreference) accessPoint.getTag()).refresh(); 787 } 788 789 @Override 790 public void onLevelChanged(AccessPoint accessPoint) { 791 ((AccessPointPreference) accessPoint.getTag()).onLevelChanged(); 792 } 793 794 public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = 795 new BaseSearchIndexProvider() { 796 @Override 797 public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) { 798 final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>(); 799 final Resources res = context.getResources(); 800 801 // Add fragment title 802 SearchIndexableRaw data = new SearchIndexableRaw(context); 803 data.title = res.getString(R.string.wifi_settings); 804 data.screenTitle = res.getString(R.string.wifi_settings); 805 data.keywords = res.getString(R.string.keywords_wifi); 806 result.add(data); 807 808 // Add saved Wi-Fi access points 809 final Collection<AccessPoint> accessPoints = 810 WifiTracker.getCurrentAccessPoints(context, true, false); 811 for (AccessPoint accessPoint : accessPoints) { 812 data = new SearchIndexableRaw(context); 813 data.title = accessPoint.getSsid(); 814 data.screenTitle = res.getString(R.string.wifi_settings); 815 data.enabled = enabled; 816 result.add(data); 817 } 818 819 return result; 820 } 821 }; 822} 823