/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.wifi;
import com.android.settings.ProgressCategory;
import com.android.settings.R;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.preference.CheckBoxPreference;
import android.provider.Settings;
import android.util.Log;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AdapterView;
import android.widget.Toast;
import android.widget.AdapterView.AdapterContextMenuInfo;
import java.util.Set;
import java.util.WeakHashMap;
/**
* Settings screen for WiFi. This will be launched from the main system settings.
*/
public class WifiSettings extends PreferenceActivity implements WifiLayer.Callback,
DialogInterface.OnDismissListener {
private static final String TAG = "WifiSettings";
//============================
// Preference/activity member variables
//============================
private static final String INSTANCE_KEY_DIALOG_BUNDLE =
"com.android.settings.wifi.WifiSettings:dialogBundle";
/*
* We don't use Activity's dialog management because AlertDialog isn't fully
* able to change many of its features after it's been created, and the
* dialog management only creates once.
*/
private Dialog mDialog;
private static final String KEY_ADD_OTHER_NETWORK = "add_other_network";
private static final int CONTEXT_MENU_ID_CONNECT = Menu.FIRST;
private static final int CONTEXT_MENU_ID_FORGET = Menu.FIRST + 1;
private static final int CONTEXT_MENU_ID_CHANGE_PASSWORD = Menu.FIRST + 2;
private static final int MENU_ID_SCAN = Menu.FIRST;
private static final int MENU_ID_ADVANCED = Menu.FIRST + 1;
private static final String KEY_WIFI_ENABLED = "wifi_enabled";
private static final String KEY_OPEN_NETWORK_NOTIFICATIONS_ENABLED =
"open_network_notifications_enabled";
private static final String KEY_ACCESS_POINTS = "access_points";
private ProgressCategory mApCategory;
private CheckBoxPreference mWifiEnabled;
private WifiEnabler mWifiEnabler;
private CheckBoxPreference mOpenNetworkNotificationsEnabled;
private Preference mAddOtherNetwork;
private WeakHashMap<AccessPointState, AccessPointPreference> mAps;
//============================
// Wifi member variables
//============================
private WifiLayer mWifiLayer;
//============================
// Activity lifecycle
//============================
public WifiSettings() {
mAps = new WeakHashMap<AccessPointState, AccessPointPreference>();
mWifiLayer = new WifiLayer(this, this);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
onCreatePreferences();
mWifiLayer.onCreate();
onCreatedWifi();
mWifiLayer.onCreatedCallback();
}
/**
* Shouldn't have any dependency on the wifi layer.
*/
private void onCreatePreferences() {
addPreferencesFromResource(R.xml.wifi_settings);
final PreferenceScreen preferenceScreen = getPreferenceScreen();
mApCategory = (ProgressCategory) preferenceScreen.findPreference(KEY_ACCESS_POINTS);
// We don't want the ordering to be the order preferences are added,
// instead we want*:
// 1) preferred, visible APs
// 2) visible APs
// 3) preferred, APs out of range
// * this ordering logic is in AccessPointPreference's compareTo
mApCategory.setOrderingAsAdded(false);
mWifiEnabled = (CheckBoxPreference) preferenceScreen.findPreference(KEY_WIFI_ENABLED);
mWifiEnabler = new WifiEnabler(this, (WifiManager) getSystemService(WIFI_SERVICE),
mWifiEnabled);
mOpenNetworkNotificationsEnabled = (CheckBoxPreference) preferenceScreen
.findPreference(KEY_OPEN_NETWORK_NOTIFICATIONS_ENABLED);
mOpenNetworkNotificationsEnabled.setChecked(Settings.Secure.getInt(getContentResolver(),
Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0) == 1);
mAddOtherNetwork = preferenceScreen.findPreference(KEY_ADD_OTHER_NETWORK);
registerForContextMenu(getListView());
}
private void onCreatedWifi() {
}
@Override
protected void onResume() {
super.onResume();
mWifiLayer.onResume();
mWifiEnabler.resume();
}
@Override
protected void onPause() {
super.onPause();
mWifiLayer.onPause();
mWifiEnabler.pause();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mDialog != null) {
mDialog.dismiss();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
menu.add(0, MENU_ID_SCAN, 0, R.string.scan_wifi)
.setIcon(R.drawable.ic_menu_scan_network);
menu.add(0, MENU_ID_ADVANCED, 0, R.string.wifi_menu_advanced)
.setIcon(android.R.drawable.ic_menu_manage);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
switch (item.getItemId()) {
case MENU_ID_SCAN:
mWifiLayer.attemptScan();
return true;
case MENU_ID_ADVANCED:
Intent intent = new Intent(this, AdvancedSettings.class);
startActivity(intent);
return true;
default:
return false;
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mDialog != null) {
Bundle dialogBundle = mDialog.onSaveInstanceState();
outState.putBundle(INSTANCE_KEY_DIALOG_BUNDLE, dialogBundle);
}
}
@Override
protected void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
Bundle dialogBundle = state.getBundle(INSTANCE_KEY_DIALOG_BUNDLE);
if (dialogBundle != null) {
mDialog = new AccessPointDialog(this, mWifiLayer);
mDialog.onRestoreInstanceState(dialogBundle);
showDialog(mDialog);
}
}
/**
* {@inheritDoc}
*/
public void onDismiss(DialogInterface dialog) {
if (dialog == mDialog) {
mDialog = null;
}
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
AccessPointState state = getStateFromMenuInfo(menuInfo);
if (state == null) {
return;
}
menu.setHeaderTitle(state.getHumanReadableSsid());
if (state.isConnectable()) {
menu.add(0, CONTEXT_MENU_ID_CONNECT, 0, R.string.wifi_context_menu_connect);
}
if (state.isForgetable()) {
menu.add(0, CONTEXT_MENU_ID_FORGET, 1, R.string.wifi_context_menu_forget);
if (state.hasPassword()) {
menu.add(0, CONTEXT_MENU_ID_CHANGE_PASSWORD, 2,
R.string.wifi_context_menu_change_password);
}
}
}
@Override
public boolean onContextItemSelected(MenuItem item) {
AccessPointState state = getStateFromMenuInfo(item.getMenuInfo());
if (state == null) {
return false;
}
switch (item.getItemId()) {
case CONTEXT_MENU_ID_CONNECT:
connectToNetwork(state);
return true;
case CONTEXT_MENU_ID_FORGET:
mWifiLayer.forgetNetwork(state);
return true;
case CONTEXT_MENU_ID_CHANGE_PASSWORD:
showAccessPointDialog(state, AccessPointDialog.MODE_CONFIGURE);
return true;
default:
return false;
}
}
/**
* Decides what needs to happen to connect to a particular access point. If
* it is secured and doesn't already have a password, it will bring up a
* password box. Otherwise it will just connect.
*/
private void connectToNetwork(AccessPointState state) {
if (state.hasSecurity() && !state.hasPassword()) {
showAccessPointDialog(state, AccessPointDialog.MODE_INFO);
} else {
mWifiLayer.connectToNetwork(state);
}
}
private AccessPointState getStateFromMenuInfo(ContextMenuInfo menuInfo) {
if ((menuInfo == null) || !(menuInfo instanceof AdapterContextMenuInfo)) {
return null;
}
AdapterContextMenuInfo adapterMenuInfo = (AdapterContextMenuInfo) menuInfo;
Preference pref = (Preference) getPreferenceScreen().getRootAdapter().getItem(
adapterMenuInfo.position);
if (pref == null || !(pref instanceof AccessPointPreference)) {
return null;
}
return ((AccessPointPreference) pref).getAccessPointState();
}
//============================
// Preference callbacks
//============================
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
super.onPreferenceTreeClick(preferenceScreen, preference);
if (preference == mAddOtherNetwork) {
showAddOtherNetworkDialog();
} else if (preference == mOpenNetworkNotificationsEnabled) {
Settings.Secure.putInt(getContentResolver(),
Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
mOpenNetworkNotificationsEnabled.isChecked() ? 1 : 0);
} else if (preference instanceof AccessPointPreference) {
AccessPointState state = ((AccessPointPreference) preference).getAccessPointState();
showAccessPointDialog(state, AccessPointDialog.MODE_INFO);
}
return false;
}
//============================
// Wifi-related
//============================
public WifiLayer getWifiLayer() {
return mWifiLayer;
}
private void showAddOtherNetworkDialog() {
AccessPointDialog dialog = new AccessPointDialog(this, mWifiLayer);
dialog.setState(new AccessPointState(this));
dialog.setMode(AccessPointDialog.MODE_CONFIGURE);
dialog.setTitle(R.string.wifi_add_other_network);
dialog.setAutoSecurityAllowed(false);
showDialog(dialog);
}
public void showAccessPointDialog(AccessPointState state, int mode) {
AccessPointDialog dialog = new AccessPointDialog(this, mWifiLayer);
dialog.setMode(mode);
dialog.setState(state);
showDialog(dialog);
}
private void showDialog(Dialog dialog) {
// Have only one dialog open at a time
if (mDialog != null) {
mDialog.dismiss();
}
mDialog = dialog;
dialog.setOnDismissListener(this);
if (dialog != null) {
dialog.show();
}
}
//============================
// Wifi callbacks
//============================
public void onError(int messageResId) {
Toast.makeText(this, messageResId, Toast.LENGTH_LONG).show();
}
public void onScanningStatusChanged(boolean started) {
mApCategory.setProgress(started);
}
public void onAccessPointSetChanged(AccessPointState ap, boolean added) {
AccessPointPreference pref = mAps.get(ap);
if (WifiLayer.LOGV) {
Log.v(TAG, "onAccessPointSetChanged with " + ap + " and "
+ (added ? "added" : "removed") + ", found pref " + pref);
}
if (added) {
if (pref == null) {
pref = new AccessPointPreference(this, ap);
mAps.put(ap, pref);
} else {
pref.setEnabled(true);
}
mApCategory.addPreference(pref);
} else {
mAps.remove(ap);
if (pref != null) {
mApCategory.removePreference(pref);
}
}
}
public void onAccessPointsStateChanged(boolean enabled) {
if (enabled) {
mApCategory.setEnabled(true);
} else {
mApCategory.removeAll();
mAps.clear();
}
mAddOtherNetwork.setEnabled(enabled);
}
public void onRetryPassword(AccessPointState ap) {
if ((mDialog != null) && mDialog.isShowing()) {
// If we're already showing a dialog, ignore this request
return;
}
showAccessPointDialog(ap, AccessPointDialog.MODE_RETRY_PASSWORD);
}
}
|