WifiSettings: revise and add support for editing EAP networks.

Use arrays.xml to store translations for enumerations;
avoid race conditions happened when pop up menu or dialog;
avoid saving configurations with networks disabled;
use the same layout for all the dialogs;
support editing EAP networks;
only unlock keystore before connecting;
and many bug fixes I cannot remember.

The number of lines in the new code is about 1/3 of the old one,
and it improves the readability a lot!
This commit is contained in:
Chia-chi Yeh
2010-01-25 15:41:42 +08:00
parent 497acbaa59
commit 48090d4066
11 changed files with 1530 additions and 106 deletions

View File

@@ -93,7 +93,23 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".wifi.AdvancedSettings" android:label="@string/wifi_ip_settings_titlebar" <activity android:name=".wifi.WifiSettings2"
android:label="@string/wifi_settings"
android:configChanges="orientation|keyboardHidden"
android:clearTaskOnLaunch="true"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.settings.WIFI_SETTINGS" />
<action android:name="android.net.wifi.PICK_WIFI_NETWORK" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.VOICE_LAUNCH" />
<category android:name="com.android.settings.SHORTCUT" />
</intent-filter>
</activity>
<activity android:name=".wifi.AdvancedSettings"
android:label="@string/wifi_ip_settings_titlebar"
> >
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />

161
res/layout/wifi_dialog.xml Normal file
View File

@@ -0,0 +1,161 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 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.
-->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="300sp"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dip"
android:orientation="vertical">
<LinearLayout android:id="@+id/info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
<LinearLayout android:id="@+id/type"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone">
<TextView
style="?android:attr/textAppearanceSmallInverse"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dip"
android:text="@string/wifi_ssid" />
<EditText android:id="@+id/ssid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:inputType="textNoSuggestions" />
<TextView
style="?android:attr/textAppearanceSmallInverse"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dip"
android:text="@string/wifi_security" />
<Spinner android:id="@+id/security"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:prompt="@string/wifi_security"
android:entries="@array/wifi_security" />
</LinearLayout>
<LinearLayout android:id="@+id/fields"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone">
<LinearLayout android:id="@+id/eap"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone">
<TextView
style="?android:attr/textAppearanceSmallInverse"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dip"
android:text="@string/wifi_eap_method" />
<Spinner android:id="@+id/method"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:prompt="@string/wifi_eap_method"
android:entries="@array/wifi_eap_method" />
<TextView
style="?android:attr/textAppearanceSmallInverse"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dip"
android:text="@string/wifi_eap_ca_cert" />
<Spinner android:id="@+id/ca_cert"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:prompt="@string/wifi_eap_ca_cert" />
<TextView
style="?android:attr/textAppearanceSmallInverse"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dip"
android:text="@string/wifi_eap_user_cert" />
<Spinner android:id="@+id/user_cert"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:prompt="@string/wifi_eap_user_cert" />
<TextView
style="?android:attr/textAppearanceSmallInverse"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dip"
android:text="@string/wifi_eap_identity" />
<EditText android:id="@+id/identity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:inputType="textNoSuggestions" />
<TextView
style="?android:attr/textAppearanceSmallInverse"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dip"
android:text="@string/wifi_eap_anonymous" />
<EditText android:id="@+id/anonymous"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:inputType="textNoSuggestions" />
</LinearLayout>
<TextView
style="?android:attr/textAppearanceSmallInverse"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dip"
android:text="@string/wifi_password" />
<EditText android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:password="true" />
<CheckBox android:id="@+id/show_password"
style="?android:attr/textAppearanceSmallInverse"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/wifi_show_password" />
</LinearLayout>
</LinearLayout>
</ScrollView>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="8dip"
android:textAppearance="?android:attr/textAppearanceSmallInverse" />
<TextView
android:id="@+id/value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmallInverse"
android:textStyle="bold" />
</LinearLayout>

View File

@@ -230,6 +230,39 @@
<item>Unsuccessful</item> <item>Unsuccessful</item>
</string-array> </string-array>
<!-- Match this with the constants in AccessPoint. --> <skip />
<!-- Wi-Fi settings. The type of security a Wi-Fi network has. -->
<string-array name="wifi_security">
<!-- The Wi-Fi network does not have any security. -->
<item>Open</item>
<!-- Do not translate. -->
<item>WEP</item>
<!-- Do not translate. -->
<item>WPA/WPA2 PSK</item>
<!-- Do not translate. -->
<item>802.1x EAP</item>
</string-array>
<!-- Match this with the constants in WifiDialog. --> <skip />
<!-- Wi-Fi settings. The type of EAP method a Wi-Fi network has. -->
<string-array name="wifi_eap_method">
<!-- Do not translate. -->
<item>PEAP</item>
<!-- Do not translate. -->
<item>TLS</item>
<!-- Do not translate. -->
<item>TTLS</item>
</string-array>
<!-- Match this with drawable.wifi_signal. --> <skip />
<!-- Wi-Fi settings. The signal strength a Wi-Fi network has. -->
<string-array name="wifi_signal">
<item>Poor</item>
<item>Fair</item>
<item>Good</item>
<item>Excellent</item>
</string-array>
<!-- Match this with code. --> <skip /> <!-- Match this with code. --> <skip />
<!-- Wi-Fi settings. The type of security a Wi-Fi network has. The user can choose this when he adds a manual network, or configures an existing network. --> <!-- Wi-Fi settings. The type of security a Wi-Fi network has. The user can choose this when he adds a manual network, or configures an existing network. -->
<string-array name="wifi_security_entries"> <string-array name="wifi_security_entries">

View File

@@ -660,7 +660,7 @@
<!-- Bluetooth settings. Dock Setting Dialog - Remember setting and don't ask user again --> <!-- Bluetooth settings. Dock Setting Dialog - Remember setting and don't ask user again -->
<string name="bluetooth_dock_settings_remember">Remember settings</string> <string name="bluetooth_dock_settings_remember">Remember settings</string>
<!-- Wi-Fi settings --> <!-- Wi-Fi Settings --> <skip />
<!-- Used in the 2nd-level settings screen to turn on Wi-Fi --> <!-- Used in the 2nd-level settings screen to turn on Wi-Fi -->
<string name="wifi">Wi-Fi</string> <string name="wifi">Wi-Fi</string>
<!-- Used in the 1st-level settings screen to turn on Wi-Fi --> <!-- Used in the 1st-level settings screen to turn on Wi-Fi -->
@@ -671,12 +671,127 @@
<string name="wifi_settings">Wi-Fi settings</string> <string name="wifi_settings">Wi-Fi settings</string>
<!-- Title of the Wi-fi settings screen --> <!-- Title of the Wi-fi settings screen -->
<string name="wifi_settings_category">Wi-Fi settings</string> <string name="wifi_settings_category">Wi-Fi settings</string>
<!--Wireless controls setting screen, Wi-Fi settings summary text --> <!-- Summary text of the Wi-fi settings screen -->
<string name="wifi_settings_summary">Set up &amp; manage wireless access points</string> <string name="wifi_settings_summary">Set up &amp; manage wireless access points</string>
<!-- Summary text when turning Wi-Fi or bluetooth on -->
<string name="wifi_starting">Turning on\u2026</string>
<!-- Summary text when turning Wi-Fi or bluetooth off -->
<string name="wifi_stopping">Turning off\u2026</string>
<!-- Summary text when Wi-Fi or bluetooth has error -->
<string name="wifi_error">Error</string>
<!-- Toast message when Wi-Fi or bluetooth is disallowed in airplane mode -->
<string name="wifi_in_airplane_mode">In airplane mode</string>
<!-- Toast message when Wi-Fi cannot scan for networks -->
<string name="wifi_fail_to_scan">Unable to scan for networks</string>
<!-- Checkbox title for option to notify user when open networks are nearby -->
<string name="wifi_notify_open_networks">Network notification</string>
<!-- Checkbox summary for option to notify user when open networks are nearby -->
<string name="wifi_notify_open_networks_summary">Notify me when an open network is available</string>
<!-- Action message to manually add a wifi network -->
<string name="wifi_add_network">Add Wi-Fi network</string>
<!-- Header for the list of wifi networks-->
<string name="wifi_access_points">Wi-Fi networks</string>
<!-- Menu option to scan Wi-Fi networks -->
<string name="wifi_menu_scan">Scan</string>
<!-- Menu option to Wi-Fi advanced settings -->
<string name="wifi_menu_advanced">Advanced</string>
<!-- Menu option to connect to a Wi-Fi network -->
<string name="wifi_menu_connect">Connect to network</string>
<!-- Menu option to delete a Wi-Fi network -->
<string name="wifi_menu_forget">Forget network</string>
<!-- Menu option to modify a Wi-Fi network configuration -->
<string name="wifi_menu_modify">Modify network</string>
<!-- Dialog for Access Points --> <skip />
<!-- Label for the SSID of the network -->
<string name="wifi_ssid">Network SSID</string>
<!-- Label for the security of the connection -->
<string name="wifi_security">Security</string>
<!-- Label for the signal strength of the connection -->
<string name="wifi_signal">Signal strength</string>
<!-- Label for the status of the connection -->
<string name="wifi_status">Status</string>
<!-- Label for the link speed of the connection -->
<string name="wifi_speed">Link speed</string>
<!-- Label for the IP address of the connection -->
<string name="wifi_ip_address">IP address</string>
<!-- Label for the EAP method of the network -->
<string name="wifi_eap_method">EAP method</string>
<!-- Label for the EAP CA certificate of the network -->
<string name="wifi_eap_ca_cert">CA certificate</string>
<!-- Label for the EAP user certificate of the network -->
<string name="wifi_eap_user_cert">User certificate</string>
<!-- Label for the EAP identity of the network -->
<string name="wifi_eap_identity">Identity</string>
<!-- Label for the EAP anonymous identity of the network -->
<string name="wifi_eap_anonymous">Anonymous identity</string>
<!-- Label for the password of the secured network -->
<string name="wifi_password">Password</string>
<!-- Label for the check box to show password -->
<string name="wifi_show_password">Show password.</string>
<!-- Hint for unchanged fields -->
<string name="wifi_unchanged">(unchanged)</string>
<!-- Hint for unspecified fields -->
<string name="wifi_unspecified">(unspecified)</string>
<!-- Summary for the remembered network. -->
<string name="wifi_remembered">Remembered</string>
<!-- Summary for the disabled network. -->
<string name="wifi_disabled">Disabled</string>
<!-- Summary for the remembered network but currently not in range. -->
<string name="wifi_not_in_range">Not in range</string>
<!-- Summary for the secured network. -->
<string name="wifi_secured">Secured with <xliff:g id="wifi_security">%1$s</xliff:g></string>
<!-- Summary for the secured and remembered network. Status can be "Remembered", "Disabled" or "Not in range". -->
<string name="wifi_secured_with_status"><xliff:g id="wifi_status">%2$s</xliff:g>, secured with <xliff:g id="wifi_security">%1$s</xliff:g></string>
<!-- Button label to connect to a Wi-Fi network -->
<string name="wifi_connect">Connect</string>
<!-- Button label to delete a Wi-Fi network -->
<string name="wifi_forget">Forget</string>
<!-- Button label to save a Wi-Fi network configuration -->
<string name="wifi_save">Save</string>
<!-- Button label to dismiss the dialog -->
<string name="wifi_cancel">Cancel</string>
<!-- Wi-Fi Advanced Settings --> <skip />
<!-- Wi-Fi settings screen, advanced, settings section. This is a header shown above advanced wifi settings. -->
<string name="wifi_advanced_titlebar">Advanced</string>
<!-- Wi-Fi settings screen, setting title for choosing the number of channels to be used -->
<string name="wifi_setting_num_channels_title">Regulatory domain</string>
<!-- Wi-Fi settings screen, setting summary for choosing the number of channels to be used -->
<string name="wifi_setting_num_channels_summary">Set the number of channels to use</string>
<!-- Wi-Fi settings screen, generic error message when the regulatory domain could not be set. -->
<string name="wifi_setting_num_channels_error">There was a problem setting the regulatory domain.</string>
<!-- Wi-Fi settings screen, label to be appended to the count in displaying the list of valid channel counts -->
<string name="wifi_setting_num_channels_channel_phrase"><xliff:g id="num_channels">%1$d</xliff:g> channels</string>
<!-- Wi-Fi settings screen, setting title for setting the wifi sleep policy -->
<string name="wifi_setting_sleep_policy_title">Wi-Fi sleep policy</string>
<!-- Wi-Fi settings screen, setting summary for setting the wifi sleep policy -->
<string name="wifi_setting_sleep_policy_summary">Specify when to switch from Wi-Fi to mobile data</string>
<!-- Wi-Fi settings screen, generic error message when the sleep policy could not be set. -->
<string name="wifi_setting_sleep_policy_error">There was a problem setting the sleep policy.</string>
<!-- Wi-Fi settings screen, advanced, title of the item to show the Wi-Fi device's MAC address. -->
<string name="wifi_advanced_mac_address_title">MAC address</string>
<!-- Title of the screen to adjust IP settings -->
<string name="wifi_ip_settings_titlebar">IP settings</string>
<!-- Menu ietm to save the IP settings -->
<string name="wifi_ip_settings_menu_save">Save</string>
<!-- Menu ietm to cancel the IP settings -->
<string name="wifi_ip_settings_menu_cancel">Cancel</string>
<!-- Error message if the IP address is not valid -->
<string name="wifi_ip_settings_invalid_ip">Please type a valid IP address.</string>
<!-- Checkbox for whether to use a static IP address -->
<string name="wifi_use_static_ip">Use static IP</string>
<!-- Label for the DNS (first one) -->
<string name="wifi_dns1">DNS 1</string>
<!-- Label for the DNS (second one)-->
<string name="wifi_dns2">DNS 2</string>
<!-- Label for the gateway of the network -->
<string name="wifi_gateway">Gateway</string>
<!-- Label for the netmask of the network -->
<string name="wifi_netmask">Netmask</string>
<!-- Button caption to forget a wifi network --> <!-- Button caption to forget a wifi network -->
<string name="forget_network">Forget</string> <string name="forget_network">Forget</string>
<!-- Label for status of connection -->
<string name="wifi_status">Status</string>
<!-- Label for link speed (wifi) --> <!-- Label for link speed (wifi) -->
<string name="wifi_link_speed">Speed</string> <string name="wifi_link_speed">Speed</string>
<!-- Verbose wifi signal strength. This is the best out of 4 levels. --> <!-- Verbose wifi signal strength. This is the best out of 4 levels. -->
@@ -709,18 +824,8 @@
<string name="wifi_security_verbose_psk">secured with WPA/WPA2 PSK</string> <string name="wifi_security_verbose_psk">secured with WPA/WPA2 PSK</string>
<!-- Verbose security type of a wifi network. Capitalized by app. --> <!-- Verbose security type of a wifi network. Capitalized by app. -->
<string name="wifi_security_verbose_eap">secured with 802.1x EAP</string> <string name="wifi_security_verbose_eap">secured with 802.1x EAP</string>
<!-- Wi-Fi IP addrress label -->
<string name="ip_address">IP address</string>
<!-- Label for the signal strength --> <!-- Label for the signal strength -->
<string name="signal">Signal strength</string> <string name="signal">Signal strength</string>
<!--Summary text when turning Wi-Fi or bluetooth on -->
<string name="wifi_starting">Turning on\u2026</string>
<!--Summary text when turning Wi-Fi or bluetooth off -->
<string name="wifi_stopping">Turning off\u2026</string>
<!-- Summary text when Wi-Fi or bluetooth has error -->
<string name="wifi_error">Error</string>
<!-- Toast message when Wi-Fi or bluetooth is disallowed in airplane mode -->
<string name="wifi_in_airplane_mode">In airplane mode</string>
<!-- Error message when Wi-Fi can't start --> <!-- Error message when Wi-Fi can't start -->
<string name="error_starting">Unable to start Wi-Fi</string> <string name="error_starting">Unable to start Wi-Fi</string>
<!-- Error message when Wi-Fi can't stop --> <!-- Error message when Wi-Fi can't stop -->
@@ -734,7 +839,7 @@
<!-- Button label to connect to a wifi network--> <!-- Button label to connect to a wifi network-->
<string name="connect">Connect</string> <string name="connect">Connect</string>
<!-- Dialog title for when the user is trying to connect to a particular network--> <!-- Dialog title for when the user is trying to connect to a particular network-->
<string name="connect_to_blank">Connect to <xliff:g id="network_name">%1$s</xliff:g></string> <string name="connect_to_blank"><xliff:g id="network_name">%1$s</xliff:g></string>
<!-- Caption for the eap method --> <!-- Caption for the eap method -->
<string name="please_select_eap">EAP method</string> <string name="please_select_eap">EAP method</string>
<!-- Caption for the phase2 --> <!-- Caption for the phase2 -->
@@ -751,8 +856,6 @@
<string name="please_type_passphrase">Wireless password</string> <string name="please_type_passphrase">Wireless password</string>
<!--Wi-Fi settings screen, connect to network dialog box, field label and hint text --> <!--Wi-Fi settings screen, connect to network dialog box, field label and hint text -->
<string name="please_type_hex_key">WEP hex key (0-9, A-F)</string> <string name="please_type_hex_key">WEP hex key (0-9, A-F)</string>
<!--Wi-Fi settings screen, connect to network dialog box, check box label -->
<string name="wifi_show_password">Show password.</string>
<!--Wi-Fi settings screen menu option --> <!--Wi-Fi settings screen menu option -->
<string name="scan_wifi">Scan</string> <string name="scan_wifi">Scan</string>
<!-- Wifi network summary when not in nearby. --> <!-- Wifi network summary when not in nearby. -->
@@ -761,48 +864,18 @@
<string name="summary_remembered">remembered</string> <string name="summary_remembered">remembered</string>
<!-- Wifi network summary when there was an error connecting --> <!-- Wifi network summary when there was an error connecting -->
<string name="summary_connection_failed">Connection unsuccessful, touch to try again</string> <string name="summary_connection_failed">Connection unsuccessful, touch to try again</string>
<!-- Header for the list of wifi networks-->
<string name="wifi_access_points">Wi-Fi networks</string>
<!-- Caption for entering the SSID of a wifi network --> <!-- Caption for entering the SSID of a wifi network -->
<string name="wifi_type_ssid">Network SSID</string> <string name="wifi_type_ssid">Network SSID</string>
<!-- The label for security -->
<string name="wifi_security">Security</string>
<!-- Button caption to save a configuration wifi --> <!-- Button caption to save a configuration wifi -->
<string name="wifi_save_config">Save</string> <string name="wifi_save_config">Save</string>
<!-- An edit field's grayed out value when it has not been modified --> <!-- An edit field's grayed out value when it has not been modified -->
<string name="wifi_password_unchanged">(unchanged)</string> <string name="wifi_password_unchanged">(unchanged)</string>
<!-- Action message to add a wifi network --> <!-- Action message to add a wifi network -->
<string name="wifi_add_other_network">Add Wi-Fi network</string> <string name="wifi_add_other_network">Add Wi-Fi network</string>
<!-- Checkbox title for option to notify user when open networks are nearby -->
<string name="wifi_notify_open_networks">Network notification</string>
<!-- Checkbox summary for option to notify user when open networks are nearby -->
<string name="wifi_notify_open_networks_summary">Notify me when an open network is available</string>
<!-- This dialog will use the error_title as the title. --> <!-- This dialog will use the error_title as the title. -->
<string name="wifi_password_incorrect_error">The network password you typed is not correct. Please try again.</string> <string name="wifi_password_incorrect_error">The network password you typed is not correct. Please try again.</string>
<!-- Generic error message --> <!-- Generic error message -->
<string name="wifi_generic_connection_error">There is a problem connecting to the network. Please try again.</string> <string name="wifi_generic_connection_error">There is a problem connecting to the network. Please try again.</string>
<!--Wi-Fi settings screen menu option -->
<string name="wifi_menu_advanced">Advanced</string>
<!-- Title of the screen to adjust IP settings -->
<string name="wifi_ip_settings_titlebar">IP settings</string>
<!-- Menu ietm to save the IP settings -->
<string name="wifi_ip_settings_menu_save">Save</string>
<!-- Menu ietm to cancel the IP settings -->
<string name="wifi_ip_settings_menu_cancel">Cancel</string>
<!-- Error message if the IP address is not valid -->
<string name="wifi_ip_settings_invalid_ip">Please type a valid IP address.</string>
<!-- Checkbox for whether to use a static IP address -->
<string name="wifi_use_static_ip">Use static IP</string>
<!-- Label for the IP address -->
<string name="wifi_ip_address">IP address</string>
<!-- Label for the DNS (first one) -->
<string name="wifi_dns1">DNS 1</string>
<!-- Label for the DNS (second one)-->
<string name="wifi_dns2">DNS 2</string>
<!-- Label for the gateway of the network -->
<string name="wifi_gateway">Gateway</string>
<!-- Label for the netmask of the network -->
<string name="wifi_netmask">Netmask</string>
<!--Wi-Fi settings screen, network context menu item --> <!--Wi-Fi settings screen, network context menu item -->
<string name="wifi_context_menu_connect">Connect to network</string> <string name="wifi_context_menu_connect">Connect to network</string>
<!--Wi-Fi settings screen, network context menu item --> <!--Wi-Fi settings screen, network context menu item -->
@@ -810,31 +883,43 @@
<!--Wi-Fi settings screen, network context menu item --> <!--Wi-Fi settings screen, network context menu item -->
<string name="wifi_context_menu_change_password">Change password</string> <string name="wifi_context_menu_change_password">Change password</string>
<!-- Wi-Fi settings screen, advanced, settings section. This is a header shown above advanced wifi settings. --> <!-- Status message of Wi-Fi when it is scanning -->
<string name="wifi_advanced_titlebar">Advanced</string> <string name="fragment_status_scanning">Scanning\u2026</string>
<!-- Wi-Fi settings screen, setting title for choosing the number of channels to be used --> <!-- Status message of Wi-Fi when it is connecting to a particular network -->
<string name="wifi_setting_num_channels_title">Regulatory domain</string> <string name="fragment_status_connecting">Connecting to <xliff:g id="network_name">%1$s</xliff:g>\u2026</string>
<!-- Wi-Fi settings screen, setting summary for choosing the number of channels to be used --> <!-- Status message of Wi-Fi when it is authenticating with a network -->
<string name="wifi_setting_num_channels_summary">Set the number of channels to use</string> <string name="fragment_status_authenticating">Authenticating with <xliff:g id="network_name">%1$s</xliff:g>\u2026</string>
<!-- Wi-Fi settings screen, generic error message when the regulatory domain could not be set. --> <!-- Status message of Wi-Fi when it is obtaining the IP address from a netwrok -->
<string name="wifi_setting_num_channels_error">There was a problem setting the regulatory domain.</string> <string name="fragment_status_obtaining_ip">Obtaining IP address from <xliff:g id="network_name">%1$s</xliff:g>\u2026</string>
<!-- Wi-Fi settings screen, label to be appended to the count in displaying the list of valid channel counts --> <!-- Status message of Wi-Fi when it is connect to a network -->
<string name="wifi_setting_num_channels_channel_phrase"><xliff:g id="num_channels">%1$d</xliff:g> channels</string> <string name="fragment_status_connected">Connected to <xliff:g id="network_name">%1$s</xliff:g></string>
<!-- Status message of Wi-Fi when it is disconnecting from a network -->
<string name="fragment_status_disconnecting">Disconnecting from <xliff:g id="network_name">%1$s</xliff:g>\u2026</string>
<!-- Status message of Wi-Fi when it is disconnected from a network-->
<string name="fragment_status_disconnected">Disconnected</string>
<!-- Status message of Wi-Fi when it is a failure (connection) -->
<string name="fragment_status_failed">Unsuccessful</string>
<!-- Wi-Fi settings screen, setting title for setting the wifi sleep policy --> <!-- Status message of Wi-Fi when it is scanning -->
<string name="wifi_setting_sleep_policy_title">Wi-Fi sleep policy</string> <string name="status_scanning">Scanning\u2026</string>
<!-- Wi-Fi settings screen, setting summary for setting the wifi sleep policy --> <!-- Status message of Wi-Fi when it is connecting (but the network is not known right now) -->
<string name="wifi_setting_sleep_policy_summary">Specify when to switch from Wi-Fi to mobile data</string> <string name="status_connecting">Connecting\u2026</string>
<!-- Wi-Fi settings screen, generic error message when the sleep policy could not be set. --> <!-- Status message of Wi-Fi when it is authenticating (but the network is not known right now) -->
<string name="wifi_setting_sleep_policy_error">There was a problem setting the sleep policy.</string> <string name="status_authenticating">Authenticating\u2026</string>
<!--Wi-Fi settings screen, summary text for network when connecting -->
<!-- Wi-Fi settings screen, advanced, title of the item to show the Wi-Fi device's MAC address. --> <string name="status_obtaining_ip">Obtaining address\u2026</string>
<string name="wifi_advanced_mac_address_title">MAC address</string> <!--Wi-Fi settings screen, summary text for network when connected -->
<string name="status_connected">Connected</string>
<!-- Status message of Wi-Fi when it is disconnecting (but the network is not known right now) -->
<string name="status_disconnecting">Disconnecting\u2026</string>
<!-- Status message of Wi-Fi when it is disconnected (but the network is not known right now) -->
<string name="status_disconnected">Disconnected</string>
<!-- Status message of Wi-Fi when it is a failure (but the network is not known right now) -->
<string name="status_failed">Unsuccessful</string>
<!-- Do not translate. Used for diagnostic screens, precise translation is not necessary <!-- Do not translate. Used for diagnostic screens, precise translation is not necessary
Wi-Fi Testing on the diagnostic screen--> Wi-Fi Testing on the diagnostic screen-->
<string name="testing_wifi_info" translatable="false">Wifi information</string> <string name="testing_wifi_info" translatable="false">Wifi information</string>
<!-- Do not translate. Used for diagnostic screens, precise translation is not necessary <!-- Do not translate. Used for diagnostic screens, precise translation is not necessary
Menu item for WifiManager disableNetwork API--> Menu item for WifiManager disableNetwork API-->
<string name="disableNetwork" translatable="false">disableNetwork</string> <string name="disableNetwork" translatable="false">disableNetwork</string>
@@ -853,7 +938,6 @@
<!-- Do not translate. Used for diagnostic screens, precise translation is not necessary <!-- Do not translate. Used for diagnostic screens, precise translation is not necessary
Menu item on Wifi information screen--> Menu item on Wifi information screen-->
<string name="wifi_api_test" translatable="false">Wifi API</string> <string name="wifi_api_test" translatable="false">Wifi API</string>
<!-- Do not translate. Used for diagnostic screens, precise translation is not necessary <!-- Do not translate. Used for diagnostic screens, precise translation is not necessary
Menu item on Wifi information screen--> Menu item on Wifi information screen-->
<string name="wifi_status_test" translatable="false">Wifi Status</string> <string name="wifi_status_test" translatable="false">Wifi Status</string>
@@ -916,41 +1000,6 @@
Label on Wifi Configuration screen--> Label on Wifi Configuration screen-->
<string name="config_list_label" translatable="false">Configured Networks</string> <string name="config_list_label" translatable="false">Configured Networks</string>
<!-- Status message of Wi-Fi when it is scanning -->
<string name="fragment_status_scanning">Scanning\u2026</string>
<!-- Status message of Wi-Fi when it is connecting to a particular network -->
<string name="fragment_status_connecting">Connecting to <xliff:g id="network_name">%1$s</xliff:g>\u2026</string>
<!-- Status message of Wi-Fi when it is authenticating with a network -->
<string name="fragment_status_authenticating">Authenticating with <xliff:g id="network_name">%1$s</xliff:g>\u2026</string>
<!-- Status message of Wi-Fi when it is obtaining the IP address from a netwrok -->
<string name="fragment_status_obtaining_ip">Obtaining IP address from <xliff:g id="network_name">%1$s</xliff:g>\u2026</string>
<!-- Status message of Wi-Fi when it is connect to a network -->
<string name="fragment_status_connected">Connected to <xliff:g id="network_name">%1$s</xliff:g></string>
<!-- Status message of Wi-Fi when it is disconnecting from a network -->
<string name="fragment_status_disconnecting">Disconnecting from <xliff:g id="network_name">%1$s</xliff:g>\u2026</string>
<!-- Status message of Wi-Fi when it is disconnected from a network-->
<string name="fragment_status_disconnected">Disconnected</string>
<!-- Status message of Wi-Fi when it is a failure (connection) -->
<string name="fragment_status_failed">Unsuccessful</string>
<!-- Status message of Wi-Fi when it is scanning -->
<string name="status_scanning">Scanning\u2026</string>
<!-- Status message of Wi-Fi when it is connecting (but the network is not known right now) -->
<string name="status_connecting">Connecting\u2026</string>
<!-- Status message of Wi-Fi when it is authenticating (but the network is not known right now) -->
<string name="status_authenticating">Authenticating\u2026</string>
<!--Wi-Fi settings screen, summary text for network when connecting -->
<string name="status_obtaining_ip">Obtaining address\u2026</string>
<!--Wi-Fi settings screen, summary text for network when connected -->
<string name="status_connected">Connected</string>
<!-- Status message of Wi-Fi when it is disconnecting (but the network is not known right now) -->
<string name="status_disconnecting">Disconnecting\u2026</string>
<!-- Status message of Wi-Fi when it is disconnected (but the network is not known right now) -->
<string name="status_disconnected">Disconnected</string>
<!-- Status message of Wi-Fi when it is a failure (but the network is not known right now) -->
<string name="status_failed">Unsuccessful</string>
<!-- Sound and alerts settings --> <!-- Sound and alerts settings -->
<!-- Main Settings screen setting option name to go into the sound settings screen --> <!-- Main Settings screen setting option name to go into the sound settings screen -->
<string name="sound_settings_title">Sound</string> <string name="sound_settings_title">Sound</string>

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 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.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/wifi_settings_category">
<com.android.settings.ProgressCategory
android:key="access_points"
android:title="@string/wifi_access_points"
android:persistent="false" />
<Preference
android:key="add_network"
android:title="@string/wifi_add_network"
android:persistent="false" />
</PreferenceScreen>

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 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.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/wifi_settings_category">
<CheckBoxPreference
android:key="enable_wifi"
android:title="@string/wifi"
android:summary="@string/wifi_quick_toggle_summary"
android:persistent="false" />
<CheckBoxPreference
android:key="notify_open_networks"
android:dependency="enable_wifi"
android:title="@string/wifi_notify_open_networks"
android:summary="@string/wifi_notify_open_networks_summary"
android:persistent="false" />
<com.android.settings.ProgressCategory
android:key="access_points"
android:dependency="enable_wifi"
android:title="@string/wifi_access_points"
android:persistent="false" />
<Preference
android:key="add_network"
android:dependency="enable_wifi"
android:title="@string/wifi_add_network"
android:persistent="false" />
</PreferenceScreen>

View File

@@ -37,7 +37,7 @@
<intent <intent
android:action="android.intent.action.MAIN" android:action="android.intent.action.MAIN"
android:targetPackage="com.android.settings" android:targetPackage="com.android.settings"
android:targetClass="com.android.settings.wifi.WifiSettings" /> android:targetClass="com.android.settings.wifi.WifiSettings2" />
</PreferenceScreen> </PreferenceScreen>
<CheckBoxPreference <CheckBoxPreference

View File

@@ -0,0 +1,212 @@
/*
* Copyright (C) 2010 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.R;
import android.content.Context;
import android.net.NetworkInfo.DetailedState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.ScanResult;
import android.preference.Preference;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;
class AccessPoint extends Preference {
private static final int[] STATE_SECURED = {R.attr.state_encrypted};
private static final int[] STATE_NONE = {};
static final int SECURITY_NONE = 0;
static final int SECURITY_WEP = 1;
static final int SECURITY_PSK = 2;
static final int SECURITY_EAP = 3;
final String ssid;
final int security;
final int networkId;
private WifiConfiguration mConfig;
private int mRssi;
private WifiInfo mInfo;
private DetailedState mState;
private ImageView mSignal;
private static int getSecurity(WifiConfiguration config) {
if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
return SECURITY_PSK;
}
if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP) ||
config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
return SECURITY_EAP;
}
return (config.wepKeys[0] != null) ? SECURITY_WEP : SECURITY_NONE;
}
private static int getSecurity(ScanResult result) {
if (result.capabilities.contains("WEP")) {
return SECURITY_WEP;
} else if (result.capabilities.contains("PSK")) {
return SECURITY_PSK;
} else if (result.capabilities.contains("EAP")) {
return SECURITY_EAP;
}
return SECURITY_NONE;
}
AccessPoint(Context context, WifiConfiguration config) {
super(context);
setWidgetLayoutResource(R.layout.preference_widget_wifi_signal);
ssid = (config.SSID == null ? "" : config.SSID);
security = getSecurity(config);
networkId = config.networkId;
mConfig = config;
mRssi = Integer.MAX_VALUE;
}
AccessPoint(Context context, ScanResult result) {
super(context);
setWidgetLayoutResource(R.layout.preference_widget_wifi_signal);
ssid = result.SSID;
security = getSecurity(result);
networkId = -1;
mRssi = result.level;
}
@Override
protected void onBindView(View view) {
setTitle(ssid);
mSignal = (ImageView) view.findViewById(R.id.signal);
if (mRssi == Integer.MAX_VALUE) {
mSignal.setImageDrawable(null);
} else {
mSignal.setImageResource(R.drawable.wifi_signal);
mSignal.setImageState((security != SECURITY_NONE) ?
STATE_SECURED : STATE_NONE, true);
}
refresh();
super.onBindView(view);
}
@Override
public int compareTo(Preference preference) {
if (!(preference instanceof AccessPoint)) {
return 1;
}
AccessPoint other = (AccessPoint) preference;
// Active one goes first.
if (mInfo != other.mInfo) {
return (mInfo != null) ? -1 : 1;
}
// Reachable one goes before unreachable one.
if ((mRssi ^ other.mRssi) < 0) {
return (mRssi != Integer.MAX_VALUE) ? -1 : 1;
}
// Configured one goes before unconfigured one.
if ((networkId ^ other.networkId) < 0) {
return (networkId != -1) ? -1 : 1;
}
// Sort by signal strength.
int difference = WifiManager.compareSignalLevel(other.mRssi, mRssi);
if (difference != 0) {
return difference;
}
// Sort by ssid.
return ssid.compareToIgnoreCase(other.ssid);
}
boolean update(ScanResult result) {
// We do not call refresh() since this is called before onBindView().
if (ssid.equals(result.SSID) && security == getSecurity(result)) {
if (WifiManager.compareSignalLevel(result.level, mRssi) > 0) {
mRssi = result.level;
}
return true;
}
return false;
}
void update(WifiInfo info, DetailedState state) {
boolean reorder = false;
if (info != null && networkId != -1 && networkId == info.getNetworkId()) {
reorder = (mInfo == null);
mRssi = info.getRssi();
mInfo = info;
mState = state;
refresh();
} else if (mInfo != null) {
reorder = true;
mInfo = null;
mState = null;
refresh();
}
if (reorder) {
notifyHierarchyChanged();
}
}
int getLevel() {
if (mRssi == Integer.MAX_VALUE) {
return -1;
}
return WifiManager.calculateSignalLevel(mRssi, 4);
}
WifiConfiguration getConfig() {
return mConfig;
}
WifiInfo getInfo() {
return mInfo;
}
DetailedState getState() {
return mState;
}
private void refresh() {
if (mSignal == null) {
return;
}
Context context = getContext();
mSignal.setImageLevel(getLevel());
if (mState != null) {
setSummary(Summary.get(context, mState));
} else {
String status = null;
if (mRssi == Integer.MAX_VALUE) {
status = context.getString(R.string.wifi_not_in_range);
} else if (mConfig != null) {
status = context.getString((mConfig.status == WifiConfiguration.Status.DISABLED) ?
R.string.wifi_disabled : R.string.wifi_remembered);
}
if (security == SECURITY_NONE) {
setSummary(status);
} else {
String format = context.getString((status == null) ?
R.string.wifi_secured : R.string.wifi_secured_with_status);
String[] type = context.getResources().getStringArray(R.array.wifi_security);
setSummary(String.format(format, type[security], status));
}
}
}
}

View File

@@ -0,0 +1,362 @@
/*
* Copyright (C) 2010 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.R;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.net.NetworkInfo.DetailedState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.AuthAlgorithm;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiInfo;
import android.os.Bundle;
import android.security.Credentials;
import android.security.KeyStore;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.text.format.Formatter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.Spinner;
import android.widget.TextView;
class WifiDialog extends AlertDialog implements View.OnClickListener,
TextWatcher, AdapterView.OnItemSelectedListener {
private static final String KEYSTORE_SPACE = "keystore://";
static final int BUTTON_SUBMIT = DialogInterface.BUTTON_POSITIVE;
static final int BUTTON_FORGET = DialogInterface.BUTTON_NEUTRAL;
final boolean edit;
private final DialogInterface.OnClickListener mListener;
private final AccessPoint mAccessPoint;
private View mView;
private TextView mSsid;
private int mSecurity;
private TextView mPassword;
private Spinner mEapMethod;
private Spinner mEapCaCert;
private Spinner mEapUserCert;
private TextView mEapIdentity;
private TextView mEapAnonymous;
static boolean requireKeyStore(WifiConfiguration config) {
String values[] = {config.ca_cert.value(), config.client_cert.value(),
config.private_key.value()};
for (String value : values) {
if (value != null && value.startsWith(KEYSTORE_SPACE)) {
return true;
}
}
return false;
}
WifiDialog(Context context, DialogInterface.OnClickListener listener,
AccessPoint accessPoint, boolean edit) {
super(context);
this.edit = edit;
mListener = listener;
mAccessPoint = accessPoint;
mSecurity = (accessPoint == null) ? AccessPoint.SECURITY_NONE : accessPoint.security;
}
WifiConfiguration getConfig() {
if (mAccessPoint != null && mAccessPoint.networkId != -1 && !edit) {
return null;
}
WifiConfiguration config = new WifiConfiguration();
if (mAccessPoint == null) {
config.SSID = mSsid.getText().toString();
// If the user adds a network manually, assume that it is hidden.
config.hiddenSSID = true;
} else if (mAccessPoint.networkId == -1) {
config.SSID = mAccessPoint.ssid;
} else {
config.networkId = mAccessPoint.networkId;
}
switch (mSecurity) {
case AccessPoint.SECURITY_NONE:
config.allowedKeyManagement.set(KeyMgmt.NONE);
return config;
case AccessPoint.SECURITY_WEP:
config.allowedKeyManagement.set(KeyMgmt.NONE);
config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
if (mPassword.length() != 0) {
int length = mPassword.length();
String password = mPassword.getText().toString();
// WEP-40, WEP-104, and 256-bit WEP (WEP-232?)
if ((length == 10 || length == 26 || length == 58) &&
password.matches("[0-9A-Fa-f]*")) {
config.wepKeys[0] = password;
} else {
config.wepKeys[0] = '"' + password + '"';
}
}
return config;
case AccessPoint.SECURITY_PSK:
config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
if (mPassword.length() != 0) {
String password = mPassword.getText().toString();
if (password.matches("[0-9A-Fa-f]{64}")) {
config.preSharedKey = password;
} else {
config.preSharedKey = '"' + password + '"';
}
}
return config;
case AccessPoint.SECURITY_EAP:
config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
config.eap.setValue((String) mEapMethod.getSelectedItem());
config.ca_cert.setValue((mEapCaCert.getSelectedItemPosition() == 0) ? "" :
KEYSTORE_SPACE + Credentials.CA_CERTIFICATE +
(String) mEapCaCert.getSelectedItem());
config.client_cert.setValue((mEapUserCert.getSelectedItemPosition() == 0) ? "" :
KEYSTORE_SPACE + Credentials.USER_CERTIFICATE +
(String) mEapUserCert.getSelectedItem());
config.private_key.setValue((mEapUserCert.getSelectedItemPosition() == 0) ? "" :
KEYSTORE_SPACE + Credentials.PRIVATE_KEY +
(String) mEapUserCert.getSelectedItem());
config.identity.setValue((mEapIdentity.length() == 0) ? "" :
mEapIdentity.getText().toString());
config.anonymous_identity.setValue((mEapAnonymous.length() == 0) ? "" :
mEapAnonymous.getText().toString());
if (mPassword.length() != 0) {
config.password.setValue(mPassword.getText().toString());
}
return config;
}
return null;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
mView = getLayoutInflater().inflate(R.layout.wifi_dialog, null);
setView(mView);
setInverseBackgroundForced(true);
Context context = getContext();
Resources resources = context.getResources();
if (mAccessPoint == null) {
setTitle(R.string.wifi_add_network);
mView.findViewById(R.id.type).setVisibility(View.VISIBLE);
mSsid = (TextView) mView.findViewById(R.id.ssid);
mSsid.addTextChangedListener(this);
((Spinner) mView.findViewById(R.id.security)).setOnItemSelectedListener(this);
setButton(BUTTON_SUBMIT, context.getString(R.string.wifi_save), mListener);
} else {
setTitle(mAccessPoint.ssid);
ViewGroup group = (ViewGroup) mView.findViewById(R.id.info);
DetailedState state = mAccessPoint.getState();
if (state != null) {
addRow(group, R.string.wifi_status, Summary.get(getContext(), state));
}
String[] type = resources.getStringArray(R.array.wifi_security);
addRow(group, R.string.wifi_security, type[mAccessPoint.security]);
int level = mAccessPoint.getLevel();
if (level != -1) {
String[] signal = resources.getStringArray(R.array.wifi_signal);
addRow(group, R.string.wifi_signal, signal[level]);
}
WifiInfo info = mAccessPoint.getInfo();
if (info != null) {
addRow(group, R.string.wifi_speed, info.getLinkSpeed() + WifiInfo.LINK_SPEED_UNITS);
// TODO: fix the ip address for IPv6.
int address = info.getIpAddress();
if (address != 0) {
addRow(group, R.string.wifi_ip_address, Formatter.formatIpAddress(address));
}
}
if (mAccessPoint.networkId == -1 || edit) {
showSecurityFields();
}
if (edit) {
setButton(BUTTON_SUBMIT, context.getString(R.string.wifi_save), mListener);
} else {
if (state == null && level != -1) {
setButton(BUTTON_SUBMIT, context.getString(R.string.wifi_connect), mListener);
}
if (mAccessPoint.networkId != -1) {
setButton(BUTTON_FORGET, context.getString(R.string.wifi_forget), mListener);
}
}
}
setButton(DialogInterface.BUTTON_NEGATIVE,
context.getString(R.string.wifi_cancel), mListener);
super.onCreate(savedInstanceState);
if (getButton(BUTTON_SUBMIT) != null) {
validate();
}
}
private void addRow(ViewGroup group, int name, String value) {
View row = getLayoutInflater().inflate(R.layout.wifi_dialog_row, group, false);
((TextView) row.findViewById(R.id.name)).setText(name);
((TextView) row.findViewById(R.id.value)).setText(value);
group.addView(row);
}
private void validate() {
// TODO: make sure this is complete.
if ((mSsid != null && mSsid.length() == 0) ||
((mAccessPoint == null || mAccessPoint.networkId == -1) &&
((mSecurity == AccessPoint.SECURITY_WEP && mPassword.length() == 0) ||
(mSecurity == AccessPoint.SECURITY_PSK && mPassword.length() < 8)))) {
getButton(BUTTON_SUBMIT).setEnabled(false);
} else {
getButton(BUTTON_SUBMIT).setEnabled(true);
}
}
public void onClick(View view) {
mPassword.setInputType(
InputType.TYPE_CLASS_TEXT | (((CheckBox) view).isChecked() ?
InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD :
InputType.TYPE_TEXT_VARIATION_PASSWORD));
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void afterTextChanged(Editable editable) {
validate();
}
public void onItemSelected(AdapterView parent, View view, int position, long id) {
mSecurity = position;
showSecurityFields();
validate();
}
public void onNothingSelected(AdapterView parent) {
}
private void showSecurityFields() {
if (mSecurity == AccessPoint.SECURITY_NONE) {
mView.findViewById(R.id.fields).setVisibility(View.GONE);
return;
}
mView.findViewById(R.id.fields).setVisibility(View.VISIBLE);
if (mPassword == null) {
mPassword = (TextView) mView.findViewById(R.id.password);
mPassword.addTextChangedListener(this);
((CheckBox) mView.findViewById(R.id.show_password)).setOnClickListener(this);
if (mAccessPoint != null && mAccessPoint.networkId != -1) {
mPassword.setHint(R.string.wifi_unchanged);
}
}
if (mSecurity != AccessPoint.SECURITY_EAP) {
mView.findViewById(R.id.eap).setVisibility(View.GONE);
return;
}
mView.findViewById(R.id.eap).setVisibility(View.VISIBLE);
if (mEapMethod == null) {
mEapMethod = (Spinner) mView.findViewById(R.id.method);
mEapCaCert = (Spinner) mView.findViewById(R.id.ca_cert);
mEapUserCert = (Spinner) mView.findViewById(R.id.user_cert);
mEapIdentity = (TextView) mView.findViewById(R.id.identity);
mEapAnonymous = (TextView) mView.findViewById(R.id.anonymous);
loadCertificates(mEapCaCert, Credentials.CA_CERTIFICATE);
loadCertificates(mEapUserCert, Credentials.USER_PRIVATE_KEY);
if (mAccessPoint != null && mAccessPoint.networkId != -1) {
WifiConfiguration config = mAccessPoint.getConfig();
setSelection(mEapMethod, config.eap.value());
setCertificate(mEapCaCert, Credentials.CA_CERTIFICATE,
config.ca_cert.value());
setCertificate(mEapUserCert, Credentials.USER_PRIVATE_KEY,
config.private_key.value());
mEapIdentity.setText(config.identity.value());
mEapAnonymous.setText(config.anonymous_identity.value());
}
}
}
private void loadCertificates(Spinner spinner, String prefix) {
String[] certs = KeyStore.getInstance().saw(prefix);
Context context = getContext();
String unspecified = context.getString(R.string.wifi_unspecified);
if (certs == null || certs.length == 0) {
certs = new String[] {unspecified};
} else {
String[] array = new String[certs.length + 1];
array[0] = unspecified;
System.arraycopy(certs, 0, array, 1, certs.length);
certs = array;
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
context, android.R.layout.simple_spinner_item, certs);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
}
private void setCertificate(Spinner spinner, String prefix, String cert) {
prefix = KEYSTORE_SPACE + prefix;
if (cert != null && cert.startsWith(prefix)) {
setSelection(spinner, cert.substring(prefix.length()));
}
}
private void setSelection(Spinner spinner, String value) {
if (value != null) {
ArrayAdapter<String> adapter = (ArrayAdapter<String>) spinner.getAdapter();
for (int i = adapter.getCount() - 1; i >= 0; --i) {
if (value.equals(adapter.getItem(i))) {
spinner.setSelection(i);
break;
}
}
}
}
}

View File

@@ -0,0 +1,484 @@
/*
* Copyright (C) 2010 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.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration.Status;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.provider.Settings.Secure;
import android.security.Credentials;
import android.security.KeyStore;
import android.text.TextUtils;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class WifiSettings2 extends PreferenceActivity implements DialogInterface.OnClickListener {
private static final int MENU_ID_SCAN = Menu.FIRST;
private static final int MENU_ID_ADVANCED = Menu.FIRST + 1;
private static final int MENU_ID_CONNECT = Menu.FIRST + 2;
private static final int MENU_ID_FORGET = Menu.FIRST + 3;
private static final int MENU_ID_MODIFY = Menu.FIRST + 4;
private final IntentFilter mFilter;
private final BroadcastReceiver mReceiver;
private final Scanner mScanner;
private WifiManager mWifiManager;
private WifiEnabler mWifiEnabler;
private CheckBoxPreference mNotifyOpenNetworks;
private ProgressCategory mAccessPoints;
private Preference mAddNetwork;
private NetworkInfo.DetailedState mLastState;
private WifiInfo mLastInfo;
private int mLastPriority;
private boolean mResetNetworks = false;
private int mKeyStoreNetworkId = -1;
private AccessPoint mSelected;
private WifiDialog mDialog;
public WifiSettings2() {
mFilter = new IntentFilter();
mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
mFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
mFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);
mFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
handleEvent(intent);
}
};
mScanner = new Scanner();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
if (getIntent().getBooleanExtra("only_access_points", false)) {
addPreferencesFromResource(R.xml.wifi_access_points2);
} else {
addPreferencesFromResource(R.xml.wifi_settings2);
mWifiEnabler = new WifiEnabler(this, mWifiManager,
(CheckBoxPreference) findPreference("enable_wifi"));
mNotifyOpenNetworks =
(CheckBoxPreference) findPreference("notify_open_networks");
mNotifyOpenNetworks.setChecked(Secure.getInt(getContentResolver(),
Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0) == 1);
}
mAccessPoints = (ProgressCategory) findPreference("access_points");
mAccessPoints.setOrderingAsAdded(false);
mAddNetwork = findPreference("add_network");
registerForContextMenu(getListView());
}
@Override
protected void onResume() {
super.onResume();
registerReceiver(mReceiver, mFilter);
if (mWifiEnabler != null) {
mWifiEnabler.resume();
}
if (mKeyStoreNetworkId != -1 && KeyStore.getInstance().test() == KeyStore.NO_ERROR) {
connect(mKeyStoreNetworkId);
}
mKeyStoreNetworkId = -1;
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mReceiver);
if (mWifiEnabler != null) {
mWifiEnabler.pause();
}
mScanner.pause();
if (mDialog != null) {
mDialog.dismiss();
mDialog = null;
}
if (mResetNetworks) {
enableNetworks();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(Menu.NONE, MENU_ID_SCAN, 0, R.string.wifi_menu_scan)
.setIcon(R.drawable.ic_menu_scan_network);
menu.add(Menu.NONE, MENU_ID_ADVANCED, 0, R.string.wifi_menu_advanced)
.setIcon(android.R.drawable.ic_menu_manage);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_ID_SCAN:
mScanner.resume();
return true;
case MENU_ID_ADVANCED:
startActivity(new Intent(this, AdvancedSettings.class));
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo info) {
if (info instanceof AdapterContextMenuInfo) {
Preference preference = (Preference) getListView().getItemAtPosition(
((AdapterContextMenuInfo) info).position);
if (preference instanceof AccessPoint) {
mSelected = (AccessPoint) preference;
menu.setHeaderTitle(mSelected.ssid);
if (mSelected.getLevel() != -1 && mSelected.getState() == null) {
menu.add(Menu.NONE, MENU_ID_CONNECT, 0, R.string.wifi_menu_connect);
}
if (mSelected.networkId != -1) {
menu.add(Menu.NONE, MENU_ID_FORGET, 0, R.string.wifi_menu_forget);
if (mSelected.security != AccessPoint.SECURITY_NONE) {
menu.add(Menu.NONE, MENU_ID_MODIFY, 0, R.string.wifi_menu_modify);
}
}
}
}
}
@Override
public boolean onContextItemSelected(MenuItem item) {
if (mSelected == null) {
return super.onContextItemSelected(item);
}
switch (item.getItemId()) {
case MENU_ID_CONNECT:
if (mSelected.networkId != -1) {
if (!requireKeyStore(mSelected.getConfig())) {
connect(mSelected.networkId);
}
} else if (mSelected.security == AccessPoint.SECURITY_NONE) {
// Shortcut for open networks.
WifiConfiguration config = new WifiConfiguration();
config.SSID = mSelected.ssid;
config.allowedKeyManagement.set(KeyMgmt.NONE);
int networkId = mWifiManager.addNetwork(config);
mWifiManager.enableNetwork(networkId, false);
connect(networkId);
} else {
showDialog(mSelected, false);
}
return true;
case MENU_ID_FORGET:
forget(mSelected.networkId);
return true;
case MENU_ID_MODIFY:
showDialog(mSelected, true);
return true;
}
return super.onContextItemSelected(item);
}
@Override
public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
if (preference instanceof AccessPoint) {
mSelected = (AccessPoint) preference;
showDialog(mSelected, false);
} else if (preference == mAddNetwork) {
mSelected = null;
showDialog(null, true);
} else if (preference == mNotifyOpenNetworks) {
Secure.putInt(getContentResolver(),
Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
mNotifyOpenNetworks.isChecked() ? 1 : 0);
} else {
return super.onPreferenceTreeClick(screen, preference);
}
return true;
}
public void onClick(DialogInterface dialogInterface, int button) {
if (button == WifiDialog.BUTTON_FORGET && mSelected != null) {
forget(mSelected.networkId);
} else if (button == WifiDialog.BUTTON_SUBMIT) {
WifiConfiguration config = mDialog.getConfig();
if (config == null) {
if (mSelected != null && !requireKeyStore(mSelected.getConfig())) {
connect(mSelected.networkId);
}
} else if (config.networkId != -1) {
if (mSelected != null) {
mWifiManager.updateNetwork(config);
saveNetworks();
}
} else {
int networkId = mWifiManager.addNetwork(config);
if (networkId != -1) {
mWifiManager.enableNetwork(networkId, false);
config.networkId = networkId;
if (mDialog.edit || requireKeyStore(config)) {
saveNetworks();
} else {
connect(networkId);
}
}
}
}
}
private void showDialog(AccessPoint accessPoint, boolean edit) {
if (mDialog != null) {
mDialog.dismiss();
}
mDialog = new WifiDialog(this, this, accessPoint, edit);
mDialog.show();
}
private boolean requireKeyStore(WifiConfiguration config) {
if (WifiDialog.requireKeyStore(config) &&
KeyStore.getInstance().test() != KeyStore.NO_ERROR) {
mKeyStoreNetworkId = config.networkId;
Credentials.getInstance().unlock(this);
return true;
}
return false;
}
private void forget(int networkId) {
mWifiManager.removeNetwork(networkId);
saveNetworks();
}
private void connect(int networkId) {
if (networkId == -1) {
return;
}
// Reset the priority of each network if it goes too high.
if (mLastPriority > 1000000) {
for (int i = mAccessPoints.getPreferenceCount() - 1; i >= 0; --i) {
AccessPoint accessPoint = (AccessPoint) mAccessPoints.getPreference(i);
if (accessPoint.networkId != -1) {
WifiConfiguration config = new WifiConfiguration();
config.networkId = accessPoint.networkId;
config.priority = 0;
mWifiManager.updateNetwork(config);
}
}
mLastPriority = 0;
}
// Set to the highest priority and save the configuration.
WifiConfiguration config = new WifiConfiguration();
config.networkId = networkId;
config.priority = ++mLastPriority;
mWifiManager.updateNetwork(config);
saveNetworks();
// Connect to network by disabling others.
mWifiManager.enableNetwork(networkId, true);
mWifiManager.reconnect();
mResetNetworks = true;
}
private void enableNetworks() {
for (int i = mAccessPoints.getPreferenceCount() - 1; i >= 0; --i) {
WifiConfiguration config = ((AccessPoint) mAccessPoints.getPreference(i)).getConfig();
if (config != null && config.status != Status.ENABLED) {
mWifiManager.enableNetwork(config.networkId, false);
}
}
mResetNetworks = false;
}
private void saveNetworks() {
// Always save the configuration with all networks enabled.
enableNetworks();
mWifiManager.saveConfiguration();
updateAccessPoints();
}
private void updateAccessPoints() {
List<AccessPoint> accessPoints = new ArrayList<AccessPoint>();
List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
if (configs != null) {
mLastPriority = 0;
for (WifiConfiguration config : configs) {
if (config.priority > mLastPriority) {
mLastPriority = config.priority;
}
// Shift the status to make enableNetworks() more efficient.
if (config.status == Status.CURRENT) {
config.status = Status.ENABLED;
} else if (mResetNetworks && config.status == Status.DISABLED) {
config.status = Status.CURRENT;
}
AccessPoint accessPoint = new AccessPoint(this, config);
accessPoint.update(mLastInfo, mLastState);
accessPoints.add(accessPoint);
}
}
List<ScanResult> results = mWifiManager.getScanResults();
if (results != null) {
for (ScanResult result : results) {
// Ignore hidden and ad-hoc networks.
if (result.SSID == null || result.SSID.length() == 0 ||
result.capabilities.contains("[IBSS]")) {
continue;
}
boolean found = false;
for (AccessPoint accessPoint : accessPoints) {
if (accessPoint.update(result)) {
found = true;
}
}
if (!found) {
accessPoints.add(new AccessPoint(this, result));
}
}
}
mAccessPoints.removeAll();
for (AccessPoint accessPoint : accessPoints) {
mAccessPoints.addPreference(accessPoint);
}
}
private void handleEvent(Intent intent) {
String action = intent.getAction();
if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
updateWifiState(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_UNKNOWN));
} else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action)) {
updateAccessPoints();
} else if (WifiManager.NETWORK_IDS_CHANGED_ACTION.equals(action)) {
if (mSelected != null && mSelected.networkId != -1) {
mSelected = null;
}
updateAccessPoints();
} else if (WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(action)) {
updateConnectionState(WifiInfo.getDetailedStateOf((SupplicantState)
intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE)));
} else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
updateConnectionState(((NetworkInfo) intent.getParcelableExtra(
WifiManager.EXTRA_NETWORK_INFO)).getDetailedState());
} else if (WifiManager.RSSI_CHANGED_ACTION.equals(action)) {
updateConnectionState(null);
}
}
private void updateConnectionState(NetworkInfo.DetailedState state) {
if (state == NetworkInfo.DetailedState.OBTAINING_IPADDR) {
mScanner.pause();
} else {
mScanner.resume();
}
mLastInfo = mWifiManager.getConnectionInfo();
if (state != null) {
mLastState = state;
}
for (int i = mAccessPoints.getPreferenceCount() - 1; i >= 0; --i) {
((AccessPoint) mAccessPoints.getPreference(i)).update(mLastInfo, mLastState);
}
}
private void updateWifiState(int state) {
if (state == WifiManager.WIFI_STATE_ENABLED) {
mScanner.resume();
updateAccessPoints();
} else {
mScanner.pause();
mAccessPoints.removeAll();
}
}
private class Scanner extends Handler {
private int mRetry = 0;
void resume() {
if (!hasMessages(0)) {
sendEmptyMessage(0);
}
}
void pause() {
mRetry = 0;
mAccessPoints.setProgress(false);
removeMessages(0);
}
@Override
public void handleMessage(Message message) {
if (mWifiManager.startScanActive()) {
mRetry = 0;
} else if (++mRetry >= 3) {
mRetry = 0;
Toast.makeText(WifiSettings2.this, R.string.wifi_fail_to_scan,
Toast.LENGTH_LONG).show();
}
mAccessPoints.setProgress(mRetry != 0);
sendEmptyMessageDelayed(0, 6000);
}
}
}