WifiSettings.java revision 1152aff9d0767e528aa4a40cc8acb51b9c21d2e7
1/* 2 * Copyright (C) 2007 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 com.android.settings.ProgressCategory; 20import com.android.settings.R; 21 22import android.app.Dialog; 23import android.content.DialogInterface; 24import android.content.Intent; 25import android.net.wifi.WifiManager; 26import android.os.Bundle; 27import android.preference.Preference; 28import android.preference.PreferenceActivity; 29import android.preference.PreferenceScreen; 30import android.preference.CheckBoxPreference; 31import android.provider.Settings; 32import android.util.Log; 33import android.view.ContextMenu; 34import android.view.Menu; 35import android.view.MenuItem; 36import android.view.View; 37import android.view.ContextMenu.ContextMenuInfo; 38import android.widget.AdapterView; 39import android.widget.Toast; 40import android.widget.AdapterView.AdapterContextMenuInfo; 41 42import java.util.Set; 43import java.util.WeakHashMap; 44 45/** 46 * Settings screen for WiFi. This will be launched from the main system settings. 47 */ 48public class WifiSettings extends PreferenceActivity implements WifiLayer.Callback, 49 DialogInterface.OnDismissListener { 50 51 private static final String TAG = "WifiSettings"; 52 53 //============================ 54 // Preference/activity member variables 55 //============================ 56 57 private static final String INSTANCE_KEY_DIALOG_BUNDLE = 58 "com.android.settings.wifi.WifiSettings:dialogBundle"; 59 /* 60 * We don't use Activity's dialog management because AlertDialog isn't fully 61 * able to change many of its features after it's been created, and the 62 * dialog management only creates once. 63 */ 64 private Dialog mDialog; 65 66 private static final String KEY_ADD_OTHER_NETWORK = "add_other_network"; 67 68 private static final int CONTEXT_MENU_ID_CONNECT = Menu.FIRST; 69 private static final int CONTEXT_MENU_ID_FORGET = Menu.FIRST + 1; 70 private static final int CONTEXT_MENU_ID_CHANGE_PASSWORD = Menu.FIRST + 2; 71 72 private static final int MENU_ID_SCAN = Menu.FIRST; 73 private static final int MENU_ID_ADVANCED = Menu.FIRST + 1; 74 75 private static final String KEY_WIFI_ENABLED = "wifi_enabled"; 76 private static final String KEY_OPEN_NETWORK_NOTIFICATIONS_ENABLED = 77 "open_network_notifications_enabled"; 78 private static final String KEY_ACCESS_POINTS = "access_points"; 79 80 private ProgressCategory mApCategory; 81 private CheckBoxPreference mWifiEnabled; 82 private WifiEnabler mWifiEnabler; 83 private CheckBoxPreference mOpenNetworkNotificationsEnabled; 84 private Preference mAddOtherNetwork; 85 86 private WeakHashMap<AccessPointState, AccessPointPreference> mAps; 87 88 //============================ 89 // Wifi member variables 90 //============================ 91 92 private WifiLayer mWifiLayer; 93 94 //============================ 95 // Activity lifecycle 96 //============================ 97 98 public WifiSettings() { 99 mAps = new WeakHashMap<AccessPointState, AccessPointPreference>(); 100 mWifiLayer = new WifiLayer(this, this); 101 } 102 103 @Override 104 protected void onCreate(Bundle savedInstanceState) { 105 super.onCreate(savedInstanceState); 106 107 onCreatePreferences(); 108 mWifiLayer.onCreate(); 109 110 onCreatedWifi(); 111 mWifiLayer.onCreatedCallback(); 112 } 113 114 /** 115 * Shouldn't have any dependency on the wifi layer. 116 */ 117 private void onCreatePreferences() { 118 addPreferencesFromResource(R.xml.wifi_settings); 119 120 final PreferenceScreen preferenceScreen = getPreferenceScreen(); 121 122 mApCategory = (ProgressCategory) preferenceScreen.findPreference(KEY_ACCESS_POINTS); 123 // We don't want the ordering to be the order preferences are added, 124 // instead we want*: 125 // 1) preferred, visible APs 126 // 2) visible APs 127 // 3) preferred, APs out of range 128 // * this ordering logic is in AccessPointPreference's compareTo 129 mApCategory.setOrderingAsAdded(false); 130 131 mWifiEnabled = (CheckBoxPreference) preferenceScreen.findPreference(KEY_WIFI_ENABLED); 132 mWifiEnabler = new WifiEnabler(this, (WifiManager) getSystemService(WIFI_SERVICE), 133 mWifiEnabled); 134 135 mOpenNetworkNotificationsEnabled = (CheckBoxPreference) preferenceScreen 136 .findPreference(KEY_OPEN_NETWORK_NOTIFICATIONS_ENABLED); 137 mOpenNetworkNotificationsEnabled.setChecked(Settings.Secure.getInt(getContentResolver(), 138 Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0) == 1); 139 140 mAddOtherNetwork = preferenceScreen.findPreference(KEY_ADD_OTHER_NETWORK); 141 142 registerForContextMenu(getListView()); 143 } 144 145 private void onCreatedWifi() { 146 } 147 148 @Override 149 protected void onResume() { 150 super.onResume(); 151 mWifiLayer.onResume(); 152 mWifiEnabler.resume(); 153 } 154 155 @Override 156 protected void onPause() { 157 super.onPause(); 158 mWifiLayer.onPause(); 159 mWifiEnabler.pause(); 160 } 161 162 @Override 163 protected void onDestroy() { 164 super.onDestroy(); 165 166 if (mDialog != null) { 167 mDialog.dismiss(); 168 } 169 } 170 171 @Override 172 public boolean onCreateOptionsMenu(Menu menu) { 173 super.onCreateOptionsMenu(menu); 174 175 menu.add(0, MENU_ID_SCAN, 0, R.string.scan_wifi) 176 .setIcon(R.drawable.ic_menu_scan_network); 177 178 menu.add(0, MENU_ID_ADVANCED, 0, R.string.wifi_menu_advanced) 179 .setIcon(android.R.drawable.ic_menu_manage); 180 181 return true; 182 } 183 184 @Override 185 public boolean onOptionsItemSelected(MenuItem item) { 186 super.onOptionsItemSelected(item); 187 188 switch (item.getItemId()) { 189 190 case MENU_ID_SCAN: 191 mWifiLayer.attemptScan(); 192 return true; 193 194 case MENU_ID_ADVANCED: 195 Intent intent = new Intent(this, AdvancedSettings.class); 196 startActivity(intent); 197 return true; 198 199 default: 200 return false; 201 } 202 } 203 204 @Override 205 protected void onSaveInstanceState(Bundle outState) { 206 super.onSaveInstanceState(outState); 207 208 if (mDialog != null) { 209 Bundle dialogBundle = mDialog.onSaveInstanceState(); 210 outState.putBundle(INSTANCE_KEY_DIALOG_BUNDLE, dialogBundle); 211 } 212 } 213 214 @Override 215 protected void onRestoreInstanceState(Bundle state) { 216 super.onRestoreInstanceState(state); 217 218 Bundle dialogBundle = state.getBundle(INSTANCE_KEY_DIALOG_BUNDLE); 219 if (dialogBundle != null) { 220 mDialog = new AccessPointDialog(this, mWifiLayer); 221 mDialog.onRestoreInstanceState(dialogBundle); 222 showDialog(mDialog); 223 } 224 } 225 226 /** 227 * {@inheritDoc} 228 */ 229 public void onDismiss(DialogInterface dialog) { 230 if (dialog == mDialog) { 231 mDialog = null; 232 } 233 } 234 235 @Override 236 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { 237 super.onCreateContextMenu(menu, v, menuInfo); 238 239 AccessPointState state = getStateFromMenuInfo(menuInfo); 240 if (state == null) { 241 return; 242 } 243 244 menu.setHeaderTitle(state.getHumanReadableSsid()); 245 246 if (state.isConnectable()) { 247 menu.add(0, CONTEXT_MENU_ID_CONNECT, 0, R.string.wifi_context_menu_connect); 248 } 249 250 if (state.isForgetable()) { 251 menu.add(0, CONTEXT_MENU_ID_FORGET, 1, R.string.wifi_context_menu_forget); 252 253 if (state.hasPassword()) { 254 menu.add(0, CONTEXT_MENU_ID_CHANGE_PASSWORD, 2, 255 R.string.wifi_context_menu_change_password); 256 } 257 } 258 } 259 260 @Override 261 public boolean onContextItemSelected(MenuItem item) { 262 263 AccessPointState state = getStateFromMenuInfo(item.getMenuInfo()); 264 if (state == null) { 265 return false; 266 } 267 268 switch (item.getItemId()) { 269 270 case CONTEXT_MENU_ID_CONNECT: 271 connectToNetwork(state); 272 return true; 273 274 case CONTEXT_MENU_ID_FORGET: 275 mWifiLayer.forgetNetwork(state); 276 return true; 277 278 case CONTEXT_MENU_ID_CHANGE_PASSWORD: 279 showAccessPointDialog(state, AccessPointDialog.MODE_CONFIGURE); 280 return true; 281 282 default: 283 return false; 284 } 285 } 286 287 /** 288 * Decides what needs to happen to connect to a particular access point. If 289 * it is secured and doesn't already have a password, it will bring up a 290 * password box. Otherwise it will just connect. 291 */ 292 private void connectToNetwork(AccessPointState state) { 293 if (state.hasSecurity() && !state.hasPassword()) { 294 showAccessPointDialog(state, AccessPointDialog.MODE_INFO); 295 } else { 296 mWifiLayer.connectToNetwork(state); 297 } 298 } 299 300 private AccessPointState getStateFromMenuInfo(ContextMenuInfo menuInfo) { 301 if ((menuInfo == null) || !(menuInfo instanceof AdapterContextMenuInfo)) { 302 return null; 303 } 304 305 AdapterContextMenuInfo adapterMenuInfo = (AdapterContextMenuInfo) menuInfo; 306 Preference pref = (Preference) getPreferenceScreen().getRootAdapter().getItem( 307 adapterMenuInfo.position); 308 if (pref == null || !(pref instanceof AccessPointPreference)) { 309 return null; 310 } 311 312 return ((AccessPointPreference) pref).getAccessPointState(); 313 } 314 315 //============================ 316 // Preference callbacks 317 //============================ 318 319 @Override 320 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { 321 super.onPreferenceTreeClick(preferenceScreen, preference); 322 323 if (preference == mAddOtherNetwork) { 324 showAddOtherNetworkDialog(); 325 } else if (preference == mOpenNetworkNotificationsEnabled) { 326 Settings.Secure.putInt(getContentResolver(), 327 Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 328 mOpenNetworkNotificationsEnabled.isChecked() ? 1 : 0); 329 } else if (preference instanceof AccessPointPreference) { 330 AccessPointState state = ((AccessPointPreference) preference).getAccessPointState(); 331 showAccessPointDialog(state, AccessPointDialog.MODE_INFO); 332 } 333 334 return false; 335 } 336 337 //============================ 338 // Wifi-related 339 //============================ 340 341 public WifiLayer getWifiLayer() { 342 return mWifiLayer; 343 } 344 345 private void showAddOtherNetworkDialog() { 346 AccessPointDialog dialog = new AccessPointDialog(this, mWifiLayer); 347 dialog.setState(new AccessPointState(this)); 348 dialog.setMode(AccessPointDialog.MODE_CONFIGURE); 349 dialog.setTitle(R.string.wifi_add_other_network); 350 dialog.setAutoSecurityAllowed(false); 351 showDialog(dialog); 352 } 353 354 public void showAccessPointDialog(AccessPointState state, int mode) { 355 AccessPointDialog dialog = new AccessPointDialog(this, mWifiLayer); 356 dialog.setMode(mode); 357 dialog.setState(state); 358 showDialog(dialog); 359 } 360 361 private void showDialog(Dialog dialog) { 362 // Have only one dialog open at a time 363 if (mDialog != null) { 364 mDialog.dismiss(); 365 } 366 367 mDialog = dialog; 368 dialog.setOnDismissListener(this); 369 if (dialog != null) { 370 dialog.show(); 371 } 372 } 373 374 //============================ 375 // Wifi callbacks 376 //============================ 377 378 public void onError(int messageResId) { 379 Toast.makeText(this, messageResId, Toast.LENGTH_LONG).show(); 380 } 381 382 public void onScanningStatusChanged(boolean started) { 383 mApCategory.setProgress(started); 384 } 385 386 public void onAccessPointSetChanged(AccessPointState ap, boolean added) { 387 388 AccessPointPreference pref = mAps.get(ap); 389 390 if (WifiLayer.LOGV) { 391 Log.v(TAG, "onAccessPointSetChanged with " + ap + " and " 392 + (added ? "added" : "removed") + ", found pref " + pref); 393 } 394 395 if (added) { 396 397 if (pref == null) { 398 pref = new AccessPointPreference(this, ap); 399 mAps.put(ap, pref); 400 } else { 401 pref.setEnabled(true); 402 } 403 404 mApCategory.addPreference(pref); 405 406 } else { 407 408 mAps.remove(ap); 409 410 if (pref != null) { 411 mApCategory.removePreference(pref); 412 } 413 414 } 415 } 416 417 public void onAccessPointsStateChanged(boolean enabled) { 418 if (enabled) { 419 mApCategory.setEnabled(true); 420 } else { 421 mApCategory.removeAll(); 422 mAps.clear(); 423 } 424 425 mAddOtherNetwork.setEnabled(enabled); 426 } 427 428 public void onRetryPassword(AccessPointState ap) { 429 430 if ((mDialog != null) && mDialog.isShowing()) { 431 // If we're already showing a dialog, ignore this request 432 return; 433 } 434 435 showAccessPointDialog(ap, AccessPointDialog.MODE_RETRY_PASSWORD); 436 } 437 438} 439