Removed some commented code, and general code cleanup. Turned many
[zxing.git] / android / src / com / google / zxing / client / android / wifi / WifiActivity.java
1 /*
2  * Copyright (C) 2010 ZXing authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.google.zxing.client.android.wifi;
18
19 import java.util.List;
20
21 import android.app.Activity;
22 import android.content.Intent;
23 import android.content.IntentFilter;
24 import android.net.ConnectivityManager;
25 import android.net.wifi.WifiConfiguration;
26 import android.net.wifi.WifiManager;
27 import android.os.Bundle;
28 import android.util.Log;
29 import android.widget.TextView;
30
31 import com.google.zxing.client.android.Intents;
32 import com.google.zxing.client.android.R;
33
34 /**
35  * A new activity showing the progress of Wifi connection
36  *
37  * TODO(viki): Tell the user when the network is not available here
38  * TODO(viki): Incorrect password, could not connect, give an error
39  * 
40  * @author Vikram Aggarwal
41  */
42 public class WifiActivity extends Activity  {
43
44   private static final String TAG = WifiActivity.class.getSimpleName();
45
46   private WifiManager wifiManager;
47   private TextView statusView;
48   private ConnectedReceiver connectedReceiver;
49
50   public enum NetworkType {
51     NETWORK_WEP, NETWORK_WPA, NETWORK_NOPASS, NETWORK_INVALID,
52   }
53
54   private int changeNetwork(NetworkSetting setting) {
55     // If the SSID is empty, throw an error and return
56     if (setting.getSsid() == null || setting.getSsid().length() == 0) {
57       return doError(R.string.wifi_ssid_missing);
58     }
59     // If the network type is invalid
60     if (setting.getNetworkType() == NetworkType.NETWORK_INVALID){
61       return doError(R.string.wifi_type_incorrect);
62     }
63
64     // If the password is empty, this is an unencrypted network
65     if (setting.getPassword() == null || setting.getPassword().length() == 0 ||
66         setting.getNetworkType() == null ||
67         setting.getNetworkType() == NetworkType.NETWORK_NOPASS) {
68       return changeNetworkUnEncrypted(setting);
69     }
70     if (setting.getNetworkType() == NetworkType.NETWORK_WPA) {
71       return changeNetworkWPA(setting);
72     } else {
73       return changeNetworkWEP(setting);
74     }
75   }
76
77   private int doError(int resource_string) {
78     statusView.setText(resource_string);
79     return -1;
80   }
81
82   private WifiConfiguration changeNetworkCommon(NetworkSetting input){
83     statusView.setText(R.string.wifi_creating_network);
84     Log.d(TAG, "Adding new configuration: \nSSID: " + input.getSsid() + "\nType: " + input.getNetworkType());
85     WifiConfiguration config = new WifiConfiguration();
86
87     config.allowedAuthAlgorithms.clear();
88     config.allowedGroupCiphers.clear();
89     config.allowedKeyManagement.clear();
90     config.allowedPairwiseCiphers.clear();
91     config.allowedProtocols.clear();
92
93     // Android API insists that an ascii SSID must be quoted to be correctly handled.
94     config.SSID = NetworkUtil.convertToQuotedString(input.getSsid());
95     config.hiddenSSID = true;
96     return config;
97   }
98
99   private int requestNetworkChange(WifiConfiguration config){
100     statusView.setText(R.string.wifi_changing_network);
101     return updateNetwork(config, false);
102   }
103
104   // Adding a WEP network
105   private int changeNetworkWEP(NetworkSetting input) {
106     WifiConfiguration config = changeNetworkCommon(input);
107     if (NetworkUtil.isHexWepKey(input.getPassword())) {
108       config.wepKeys[0] = input.getPassword();
109     } else {
110       config.wepKeys[0] = NetworkUtil.convertToQuotedString(input.getPassword());
111     }
112     config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
113     config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
114     config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
115     config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
116     config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
117     config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
118     config.wepTxKeyIndex = 0;
119     return requestNetworkChange(config);
120   }
121
122   // Adding a WPA or WPA2 network
123   private int changeNetworkWPA(NetworkSetting input) {
124     WifiConfiguration config = changeNetworkCommon(input);
125     final String pass = input.getPassword();
126     // Hex passwords that are 64 bits long are not to be quoted.
127     if (pass.matches("[0-9A-Fa-f]{64}")){
128       Log.d(TAG, "A 64 bit hex password entered.");
129       config.preSharedKey = pass;
130     } else {
131       Log.d(TAG, "A normal password entered: I am quoting it.");
132       config.preSharedKey = NetworkUtil.convertToQuotedString(pass);
133     }
134     config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
135     // For WPA
136     config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
137     // For WPA2
138     config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
139     config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
140     config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
141     config.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
142     return requestNetworkChange(config);
143   }
144
145   // Adding an open, unsecured network
146   private int changeNetworkUnEncrypted(NetworkSetting input){
147     WifiConfiguration config = changeNetworkCommon(input);
148     Log.d(TAG, "Empty password prompting a simple account setting");
149     config.wepKeys[0] = "";
150     config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
151     config.wepTxKeyIndex = 0;
152     return requestNetworkChange(config);
153   }
154
155   /**
156    * If the given ssid name exists in the settings, then change its password to the one given here, and save
157    * @param ssid
158    */
159   private WifiConfiguration findNetworkInExistingConfig(String ssid){
160     final List <WifiConfiguration> existingConfigs = wifiManager.getConfiguredNetworks();
161     for (WifiConfiguration existingConfig : existingConfigs) {
162       if (existingConfig.SSID.equals(ssid)) {
163         return existingConfig;
164       }
165     }
166     return null;
167   }
168
169   @Override
170   protected void onCreate(Bundle savedInstanceState) {
171     super.onCreate(savedInstanceState);
172
173     final Intent intent = getIntent();
174     if (intent == null || (!intent.getAction().equals(Intents.WifiConnect.ACTION))) {
175       finish();
176       return;
177     }
178
179     final String ssid = intent.getStringExtra(Intents.WifiConnect.SSID);
180     String password = intent.getStringExtra(Intents.WifiConnect.PASSWORD);
181     final String networkType = intent.getStringExtra(Intents.WifiConnect.TYPE);
182     setContentView(R.layout.network);
183     statusView = (TextView) findViewById(R.id.networkStatus);
184
185     // TODO(vikrama): Error checking here, to ensure ssid exists.
186     NetworkType networkT;
187     if (networkType.equals("WPA")) {
188       networkT = NetworkType.NETWORK_WPA;
189     } else if (networkType.equals("WEP")) {
190       networkT = NetworkType.NETWORK_WEP;
191     } else if (networkType.equals("nopass")) {
192      networkT = NetworkType.NETWORK_NOPASS;
193     } else {
194       // Got an incorrect network type.  Give an error
195       doError(R.string.wifi_type_incorrect);
196       return;
197     }
198
199     // This is not available before onCreate
200     wifiManager = (WifiManager) this.getSystemService(WIFI_SERVICE);
201
202     // So we know when the network changes
203     connectedReceiver = new ConnectedReceiver(this, statusView);
204     registerReceiver(connectedReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
205
206     if (password == null) {
207       password = "";
208     }
209     Log.d(TAG, "Adding new configuration: \nSSID: " + ssid + "Type: " + networkT);
210     NetworkSetting setting = new NetworkSetting(ssid, password, networkT);
211     changeNetwork(setting);
212   }
213
214   @Override
215   protected void onDestroy() {
216     if (connectedReceiver != null) {
217       unregisterReceiver(connectedReceiver);
218       connectedReceiver = null;
219     }
220     super.onDestroy();
221   }
222
223   /**
224    * Update the network: either create a new network or modify an existing network
225    * @param config the new network configuration
226    * @param disableOthers true if other networks must be disabled
227    * @return network ID of the connected network.
228    */
229   private int updateNetwork(WifiConfiguration config, boolean disableOthers){
230     int networkId;
231     if (findNetworkInExistingConfig(config.SSID) == null){
232       statusView.setText(R.string.wifi_creating_network);
233       networkId = wifiManager.addNetwork(config);
234     } else {
235       statusView.setText(R.string.wifi_modifying_network);
236       networkId = wifiManager.updateNetwork(config);
237     }
238     if (networkId == -1 || !wifiManager.enableNetwork(networkId, disableOthers)) {
239       return -1;
240     }
241     wifiManager.saveConfiguration();
242     return networkId;
243   }
244 }