2 * Copyright (C) 2010 ZXing authors
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.google.zxing.client.android.wifi;
19 import java.util.List;
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;
31 import com.google.zxing.client.android.Intents;
32 import com.google.zxing.client.android.R;
35 * A new activity showing the progress of Wifi connection
37 * @author Vikram Aggarwal
39 public class WifiActivity extends Activity {
41 private static final String TAG = WifiActivity.class.getSimpleName();
42 private WifiManager wifiManager;
43 private TextView statusView;
44 private WifiReceiver wifiReceiver;
45 private boolean receiverRegistered;
46 private int networkId;
47 private static int errorCount;
48 private IntentFilter mWifiStateFilter;
54 public void gotError(){
55 final int maxErrorCount = 3;
57 Log.d(TAG, "Encountered another error. Errorcount = " + errorCount);
58 if (errorCount > maxErrorCount){
60 doError(R.string.wifi_connect_failed);
64 public enum NetworkType {
65 NETWORK_WEP, NETWORK_WPA, NETWORK_NOPASS, NETWORK_INVALID,
68 private int changeNetwork(NetworkSetting setting) {
69 // If the SSID is empty, throw an error and return
70 if (setting.getSsid() == null || setting.getSsid().length() == 0) {
71 return doError(R.string.wifi_ssid_missing);
73 // If the network type is invalid
74 if (setting.getNetworkType() == NetworkType.NETWORK_INVALID){
75 return doError(R.string.wifi_type_incorrect);
78 // If the password is empty, this is an unencrypted network
79 if (setting.getPassword() == null || setting.getPassword().length() == 0 ||
80 setting.getNetworkType() == null ||
81 setting.getNetworkType() == NetworkType.NETWORK_NOPASS) {
82 return changeNetworkUnEncrypted(setting);
84 if (setting.getNetworkType() == NetworkType.NETWORK_WPA) {
85 return changeNetworkWPA(setting);
87 return changeNetworkWEP(setting);
91 private int doError(int resource_string) {
92 statusView.setText(resource_string);
93 // Give up on the connection
94 wifiManager.disconnect();
96 wifiManager.removeNetwork(networkId);
99 if (receiverRegistered) {
100 unregisterReceiver(wifiReceiver);
101 receiverRegistered = false;
106 private WifiConfiguration changeNetworkCommon(NetworkSetting input){
107 statusView.setText(R.string.wifi_creating_network);
108 Log.d(TAG, "Adding new configuration: \nSSID: " + input.getSsid() + "\nType: " + input.getNetworkType());
109 final WifiConfiguration config = new WifiConfiguration();
111 config.allowedAuthAlgorithms.clear();
112 config.allowedGroupCiphers.clear();
113 config.allowedKeyManagement.clear();
114 config.allowedPairwiseCiphers.clear();
115 config.allowedProtocols.clear();
117 // Android API insists that an ascii SSID must be quoted to be correctly handled.
118 config.SSID = NetworkUtil.convertToQuotedString(input.getSsid());
119 config.hiddenSSID = true;
123 private int requestNetworkChange(WifiConfiguration config){
124 statusView.setText(R.string.wifi_changing_network);
125 return updateNetwork(config, false);
128 // Adding a WEP network
129 private int changeNetworkWEP(NetworkSetting input) {
130 final WifiConfiguration config = changeNetworkCommon(input);
131 final String pass = input.getPassword();
132 if (NetworkUtil.isHexWepKey(pass)) {
133 config.wepKeys[0] = pass;
135 config.wepKeys[0] = NetworkUtil.convertToQuotedString(pass);
137 config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
138 config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
139 config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
140 config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
141 config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
142 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
143 config.wepTxKeyIndex = 0;
144 return requestNetworkChange(config);
147 // Adding a WPA or WPA2 network
148 private int changeNetworkWPA(NetworkSetting input) {
149 final WifiConfiguration config = changeNetworkCommon(input);
150 final String pass = input.getPassword();
151 // Hex passwords that are 64 bits long are not to be quoted.
152 if (pass.matches("[0-9A-Fa-f]{64}")){
153 Log.d(TAG, "A 64 bit hex password entered.");
154 config.preSharedKey = pass;
156 Log.d(TAG, "A normal password entered: I am quoting it.");
157 config.preSharedKey = NetworkUtil.convertToQuotedString(pass);
159 config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
161 config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
163 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
164 config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
165 config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
166 config.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
167 return requestNetworkChange(config);
170 // Adding an open, unsecured network
171 private int changeNetworkUnEncrypted(NetworkSetting input){
172 Log.d(TAG, "Empty password prompting a simple account setting");
173 WifiConfiguration config = changeNetworkCommon(input);
174 config.wepKeys[0] = "";
175 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
176 config.wepTxKeyIndex = 0;
177 return requestNetworkChange(config);
181 * If the given ssid name exists in the settings, then change its password to the one given here, and save
184 private WifiConfiguration findNetworkInExistingConfig(String ssid){
185 final List <WifiConfiguration> existingConfigs = wifiManager.getConfiguredNetworks();
186 for (final WifiConfiguration existingConfig : existingConfigs) {
187 if (existingConfig.SSID.equals(ssid)) {
188 return existingConfig;
195 protected void onCreate(Bundle savedInstanceState) {
196 super.onCreate(savedInstanceState);
198 final Intent intent = getIntent();
199 if (intent == null || (!intent.getAction().equals(Intents.WifiConnect.ACTION))) {
204 final String ssid = intent.getStringExtra(Intents.WifiConnect.SSID);
205 String password = intent.getStringExtra(Intents.WifiConnect.PASSWORD);
206 final String networkType = intent.getStringExtra(Intents.WifiConnect.TYPE);
207 setContentView(R.layout.network);
208 statusView = (TextView) findViewById(R.id.networkStatus);
210 NetworkType networkT;
211 if (networkType.equals("WPA")) {
212 networkT = NetworkType.NETWORK_WPA;
213 } else if (networkType.equals("WEP")) {
214 networkT = NetworkType.NETWORK_WEP;
215 } else if (networkType.equals("nopass")) {
216 networkT = NetworkType.NETWORK_NOPASS;
218 doError(R.string.wifi_type_incorrect);
222 // This is not available before onCreate
223 wifiManager = (WifiManager) this.getSystemService(WIFI_SERVICE);
224 // Start WiFi, otherwise nothing will work
225 wifiManager.setWifiEnabled(true);
227 // So we know when the network changes
228 wifiReceiver = new WifiReceiver(wifiManager, this, statusView, ssid);
230 // The order matters!
231 mWifiStateFilter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
232 mWifiStateFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
233 mWifiStateFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
234 mWifiStateFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
235 registerReceiver(wifiReceiver, mWifiStateFilter);
236 receiverRegistered = true;
238 if (password == null) {
241 Log.d(TAG, "Adding new configuration: \nSSID: " + ssid + "Type: " + networkT);
242 NetworkSetting setting = new NetworkSetting(ssid, password, networkT);
243 changeNetwork(setting);
246 public void pause() {
247 if (receiverRegistered) {
248 unregisterReceiver(wifiReceiver);
249 receiverRegistered = false;
253 public void resume() {
254 if (wifiReceiver != null && mWifiStateFilter != null && !receiverRegistered) {
255 registerReceiver(wifiReceiver, mWifiStateFilter);
256 receiverRegistered = true;
261 protected void onDestroy() {
262 if (wifiReceiver != null) {
263 if (receiverRegistered) {
264 unregisterReceiver(wifiReceiver);
265 receiverRegistered = false;
273 * Update the network: either create a new network or modify an existing network
274 * @param config the new network configuration
275 * @param disableOthers true if other networks must be disabled
276 * @return network ID of the connected network.
278 private int updateNetwork(WifiConfiguration config, boolean disableOthers){
279 final int FAILURE = -1;
280 WifiConfiguration found = findNetworkInExistingConfig(config.SSID);
281 wifiManager.disconnect();
283 statusView.setText(R.string.wifi_creating_network);
285 statusView.setText(R.string.wifi_modifying_network);
286 Log.d(TAG, "Removing network " + found.networkId);
287 wifiManager.removeNetwork(found.networkId);
288 wifiManager.saveConfiguration();
290 networkId = wifiManager.addNetwork(config);
291 Log.d(TAG, "Inserted/Modified network " + networkId);
295 // Try to disable the current network and start a new one.
296 if (!wifiManager.enableNetwork(networkId, disableOthers)) {
301 wifiManager.reassociate();