import java.util.List;
import android.app.Activity;
-import android.content.BroadcastReceiver;
-import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.util.Log;
-import android.widget.ImageView;
import android.widget.TextView;
import com.google.zxing.client.android.Intents;
import com.google.zxing.client.android.R;
-import com.google.zxing.client.android.wifi.Killer;
-import com.google.zxing.client.android.wifi.NetworkUtil;
-import com.google.zxing.client.android.wifi.NetworkSetting;
/**
* A new activity showing the progress of Wifi connection
+ *
* @author Vikram Aggarwal
- *
*/
public class WifiActivity extends Activity {
- public static enum NetworkType {
- NETWORK_WEP, NETWORK_WPA,
- }
- /**
- * Get a broadcast when the network is connected, and kill the activity.
- */
- class ConnectedReceiver extends BroadcastReceiver {
- Activity parent = null;
- public ConnectedReceiver(WifiActivity wifiActivity) {
- parent = wifiActivity;
- }
+ private static final String TAG = WifiActivity.class.getSimpleName();
+ private WifiManager wifiManager;
+ private TextView statusView;
+ private WifiReceiver wifiReceiver;
+ private boolean receiverRegistered;
+ private int networkId;
+ private static int errorCount;
+ private IntentFilter mWifiStateFilter;
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(android.net.ConnectivityManager.CONNECTIVITY_ACTION)){
- ConnectivityManager con = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
- NetworkInfo[] s = con.getAllNetworkInfo();
- for (NetworkInfo i : s){
- if (i.getTypeName().contentEquals("WIFI")){
- NetworkInfo.State state = i.getState();
- if (state == NetworkInfo.State.CONNECTED){
- statusT.setText("Connected!");
- Killer delay_kill = new Killer(parent);
- delay_kill.run();
- }
- }
- }
- }
+ static {
+ errorCount = 0;
+ }
+
+ public void gotError(){
+ final int maxErrorCount = 3;
+ errorCount++;
+ Log.d(TAG, "Encountered another error. Errorcount = " + errorCount);
+ if (errorCount > maxErrorCount){
+ errorCount = 0;
+ doError(R.string.wifi_connect_failed);
}
}
- private static final String tag = "NetworkActivity";
- WifiManager mWifiManager = null;
- TextView statusT = null;
- ImageView statusI = null;
- ConnectedReceiver rec = null;
- boolean debug = true;
+ public enum NetworkType {
+ NETWORK_WEP, NETWORK_WPA, NETWORK_NOPASS, NETWORK_INVALID,
+ }
private int changeNetwork(NetworkSetting setting) {
+ // If the SSID is empty, throw an error and return
+ if (setting.getSsid() == null || setting.getSsid().length() == 0) {
+ return doError(R.string.wifi_ssid_missing);
+ }
+ // If the network type is invalid
+ if (setting.getNetworkType() == NetworkType.NETWORK_INVALID){
+ return doError(R.string.wifi_type_incorrect);
+ }
+
// If the password is empty, this is an unencrypted network
- if (setting.getPassword() == null || setting.getPassword() == "") {
+ if (setting.getPassword() == null || setting.getPassword().length() == 0 ||
+ setting.getNetworkType() == null ||
+ setting.getNetworkType() == NetworkType.NETWORK_NOPASS) {
return changeNetworkUnEncrypted(setting);
}
if (setting.getNetworkType() == NetworkType.NETWORK_WPA) {
- return changeNetworkWPA(setting);
+ return changeNetworkWPA(setting);
} else {
return changeNetworkWEP(setting);
}
}
- private WifiConfiguration changeNetworkCommon(NetworkSetting input){
- statusT.setText("Creating settings...");
- if (debug) {
- Log.d(tag, "adding new configuration: \nSSID: " + input.getSsid() + "\nPassword: \""
- + input.getPassword() + "\"\nType: " + input.getNetworkType());
+ private int doError(int resource_string) {
+ statusView.setText(resource_string);
+ // Give up on the connection
+ wifiManager.disconnect();
+ if (networkId > 0) {
+ wifiManager.removeNetwork(networkId);
+ networkId = -1;
+ }
+ if (receiverRegistered) {
+ unregisterReceiver(wifiReceiver);
+ receiverRegistered = false;
}
- WifiConfiguration config = new WifiConfiguration();
+ return -1;
+ }
+
+ private WifiConfiguration changeNetworkCommon(NetworkSetting input){
+ statusView.setText(R.string.wifi_creating_network);
+ Log.d(TAG, "Adding new configuration: \nSSID: " + input.getSsid() + "\nType: " + input.getNetworkType());
+ final WifiConfiguration config = new WifiConfiguration();
config.allowedAuthAlgorithms.clear();
config.allowedGroupCiphers.clear();
config.allowedProtocols.clear();
// Android API insists that an ascii SSID must be quoted to be correctly handled.
- config.SSID = NetworkUtil.convertToQuotedString(input.getSsid());
+ config.SSID = NetworkUtil.convertToQuotedString(input.getSsid());
config.hiddenSSID = true;
return config;
}
- private int requestNetworkChange(WifiConfiguration config){
- boolean disableOthers = false;
- statusT.setText("Changing Network...");
- return updateNetwork(config, disableOthers);
+ private int requestNetworkChange(WifiConfiguration config){
+ statusView.setText(R.string.wifi_changing_network);
+ return updateNetwork(config, false);
}
// Adding a WEP network
private int changeNetworkWEP(NetworkSetting input) {
- WifiConfiguration config = changeNetworkCommon(input);
- if (NetworkUtil.isHexWepKey(input.getPassword())) {
- config.wepKeys[0] = input.getPassword();
+ final WifiConfiguration config = changeNetworkCommon(input);
+ final String pass = input.getPassword();
+ if (NetworkUtil.isHexWepKey(pass)) {
+ config.wepKeys[0] = pass;
} else {
- config.wepKeys[0] = NetworkUtil.convertToQuotedString(input.getPassword());
+ config.wepKeys[0] = NetworkUtil.convertToQuotedString(pass);
}
config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
// Adding a WPA or WPA2 network
private int changeNetworkWPA(NetworkSetting input) {
- WifiConfiguration config = changeNetworkCommon(input);
- config.preSharedKey = NetworkUtil.convertToQuotedString(input.getPassword());
+ final WifiConfiguration config = changeNetworkCommon(input);
+ final String pass = input.getPassword();
+ // Hex passwords that are 64 bits long are not to be quoted.
+ if (pass.matches("[0-9A-Fa-f]{64}")){
+ Log.d(TAG, "A 64 bit hex password entered.");
+ config.preSharedKey = pass;
+ } else {
+ Log.d(TAG, "A normal password entered: I am quoting it.");
+ config.preSharedKey = NetworkUtil.convertToQuotedString(pass);
+ }
config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
- config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
// For WPA
config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
// For WPA2
+ config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+ config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
+ config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
config.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
return requestNetworkChange(config);
}
// Adding an open, unsecured network
private int changeNetworkUnEncrypted(NetworkSetting input){
+ Log.d(TAG, "Empty password prompting a simple account setting");
WifiConfiguration config = changeNetworkCommon(input);
- if (debug){
- Log.d(tag, "Empty password prompting a simple account setting");
- }
config.wepKeys[0] = "";
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
config.wepTxKeyIndex = 0;
* @param ssid
*/
private WifiConfiguration findNetworkInExistingConfig(String ssid){
- List <WifiConfiguration> existingConfigs = mWifiManager.getConfiguredNetworks();
- for (int i = 0; i < existingConfigs.size(); i++){
- if (existingConfigs.get(i).SSID.compareTo(ssid) == 0){
- return existingConfigs.get(i);
+ final List <WifiConfiguration> existingConfigs = wifiManager.getConfiguredNetworks();
+ for (final WifiConfiguration existingConfig : existingConfigs) {
+ if (existingConfig.SSID.equals(ssid)) {
+ return existingConfig;
}
}
return null;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- Intent intent = getIntent();
+ final Intent intent = getIntent();
if (intent == null || (!intent.getAction().equals(Intents.WifiConnect.ACTION))) {
finish();
return;
}
- String ssid = intent.getStringExtra(Intents.WifiConnect.SSID);
+ final String ssid = intent.getStringExtra(Intents.WifiConnect.SSID);
String password = intent.getStringExtra(Intents.WifiConnect.PASSWORD);
- String networkType = intent.getStringExtra(Intents.WifiConnect.TYPE);
+ final String networkType = intent.getStringExtra(Intents.WifiConnect.TYPE);
+ setContentView(R.layout.network);
+ statusView = (TextView) findViewById(R.id.networkStatus);
- // TODO(vikrama): Error checking here, to ensure ssid exists.
- NetworkType networkT = null;
- if (networkType.contains("WPA")) {
+ NetworkType networkT;
+ if (networkType.equals("WPA")) {
networkT = NetworkType.NETWORK_WPA;
- }
- else if (networkType.contains("WEP")) {
+ } else if (networkType.equals("WEP")) {
networkT = NetworkType.NETWORK_WEP;
- }
- else {
- // Got an incorrect network type
- finish();
+ } else if (networkType.equals("nopass")) {
+ networkT = NetworkType.NETWORK_NOPASS;
+ } else {
+ doError(R.string.wifi_type_incorrect);
return;
}
- setContentView(R.layout.network);
- statusT = (TextView) findViewById(R.id.networkStatus);
// This is not available before onCreate
- mWifiManager = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
+ wifiManager = (WifiManager) this.getSystemService(WIFI_SERVICE);
+ // Start WiFi, otherwise nothing will work
+ wifiManager.setWifiEnabled(true);
// So we know when the network changes
- rec = new ConnectedReceiver(this);
- registerReceiver(rec, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
+ wifiReceiver = new WifiReceiver(wifiManager, this, statusView, ssid);
+
+ // The order matters!
+ mWifiStateFilter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
+ mWifiStateFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+ mWifiStateFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
+ mWifiStateFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ registerReceiver(wifiReceiver, mWifiStateFilter);
+ receiverRegistered = true;
- if (password == null)
+ if (password == null) {
password = "";
- if (debug) {
- Log.d(tag, "adding new configuration: \nSSID: " + ssid + "\nPassword: \"" + password + "\"\nType: " + networkT);
}
+ Log.d(TAG, "Adding new configuration: \nSSID: " + ssid + "Type: " + networkT);
NetworkSetting setting = new NetworkSetting(ssid, password, networkT);
changeNetwork(setting);
}
+ public void pause() {
+ if (receiverRegistered) {
+ unregisterReceiver(wifiReceiver);
+ receiverRegistered = false;
+ }
+ }
+
+ public void resume() {
+ if (wifiReceiver != null && mWifiStateFilter != null && !receiverRegistered) {
+ registerReceiver(wifiReceiver, mWifiStateFilter);
+ receiverRegistered = true;
+ }
+ }
+
@Override
protected void onDestroy() {
+ if (wifiReceiver != null) {
+ if (receiverRegistered) {
+ unregisterReceiver(wifiReceiver);
+ receiverRegistered = false;
+ }
+ wifiReceiver = null;
+ }
super.onDestroy();
- if (rec != null)
- unregisterReceiver(rec);
- rec = null;
}
/**
* Update the network: either create a new network or modify an existing network
- * @param config: the new network configuration
- * @param disableOthers: true if other networks must be disabled
+ * @param config the new network configuration
+ * @param disableOthers true if other networks must be disabled
* @return network ID of the connected network.
*/
private int updateNetwork(WifiConfiguration config, boolean disableOthers){
- WifiConfiguration existing = findNetworkInExistingConfig(config.SSID);
- int networkId;
- if (existing == null){
- statusT.setText("Creating network...");
- networkId = mWifiManager.addNetwork(config);
+ final int FAILURE = -1;
+ WifiConfiguration found = findNetworkInExistingConfig(config.SSID);
+ wifiManager.disconnect();
+ if (found == null){
+ statusView.setText(R.string.wifi_creating_network);
} else {
- statusT.setText("Modifying network...");
- networkId = mWifiManager.updateNetwork(config);
- }
- if (networkId == -1){
- return networkId;
- }
- if (!mWifiManager.enableNetwork(networkId, disableOthers)) {
- return -1;
+ statusView.setText(R.string.wifi_modifying_network);
+ Log.d(TAG, "Removing network " + found.networkId);
+ wifiManager.removeNetwork(found.networkId);
+ wifiManager.saveConfiguration();
+ }
+ networkId = wifiManager.addNetwork(config);
+ Log.d(TAG, "Inserted/Modified network " + networkId);
+ if (networkId < 0)
+ return FAILURE;
+
+ // Try to disable the current network and start a new one.
+ if (!wifiManager.enableNetwork(networkId, disableOthers)) {
+ networkId = -1;
+ return FAILURE;
}
- mWifiManager.saveConfiguration();
+ errorCount = 0;
+ wifiManager.reassociate();
return networkId;
}
}
\ No newline at end of file