2 * Copyright (C) 2011 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 cz.cvut.fel.dce.barcodescanner.wifi;
19 import android.net.wifi.WifiConfiguration;
20 import android.net.wifi.WifiManager;
21 import android.os.AsyncTask;
22 import android.util.Log;
24 import com.google.zxing.client.result.WifiParsedResult;
26 import java.util.regex.Pattern;
29 * @author Vikram Aggarwal
32 public final class WifiConfigManager extends AsyncTask<WifiParsedResult,Object,Object> {
34 private static final String TAG = WifiConfigManager.class.getSimpleName();
36 private static final Pattern HEX_DIGITS = Pattern.compile("[0-9A-Fa-f]+");
38 private final WifiManager wifiManager;
40 public WifiConfigManager(WifiManager wifiManager) {
41 this.wifiManager = wifiManager;
45 protected Object doInBackground(WifiParsedResult... args) {
46 WifiParsedResult theWifiResult = args[0];
47 // Start WiFi, otherwise nothing will work
48 if (!wifiManager.isWifiEnabled()) {
49 Log.i(TAG, "Enabling wi-fi...");
50 if (wifiManager.setWifiEnabled(true)) {
51 Log.i(TAG, "Wi-fi enabled");
53 Log.w(TAG, "Wi-fi could not be enabled!");
56 // This happens very quickly, but need to wait for it to enable. A little busy wait?
58 while (!wifiManager.isWifiEnabled()) {
60 Log.i(TAG, "Took too long to enable wi-fi, quitting");
63 Log.i(TAG, "Still waiting for wi-fi to enable...");
66 } catch (InterruptedException ie) {
72 String networkTypeString = theWifiResult.getNetworkEncryption();
73 NetworkType networkType;
75 networkType = NetworkType.forIntentValue(networkTypeString);
76 } catch (IllegalArgumentException ignored) {
77 Log.w(TAG, "Bad network type; see NetworkType values: " + networkTypeString);
80 if (networkType == NetworkType.NO_PASSWORD) {
81 changeNetworkUnEncrypted(wifiManager, theWifiResult);
83 String password = theWifiResult.getPassword();
84 if (password != null && !password.isEmpty()) {
85 if (networkType == NetworkType.WEP) {
86 changeNetworkWEP(wifiManager, theWifiResult);
87 } else if (networkType == NetworkType.WPA) {
88 changeNetworkWPA(wifiManager, theWifiResult);
96 * Update the network: either create a new network or modify an existing network
97 * @param config the new network configuration
99 private static void updateNetwork(WifiManager wifiManager, WifiConfiguration config) {
100 Integer foundNetworkID = findNetworkInExistingConfig(wifiManager, config.SSID);
101 if (foundNetworkID != null) {
102 Log.i(TAG, "Removing old configuration for network " + config.SSID);
103 wifiManager.removeNetwork(foundNetworkID);
104 wifiManager.saveConfiguration();
106 int networkId = wifiManager.addNetwork(config);
107 if (networkId >= 0) {
108 // Try to disable the current network and start a new one.
109 if (wifiManager.enableNetwork(networkId, true)) {
110 Log.i(TAG, "Associating to network " + config.SSID);
111 wifiManager.saveConfiguration();
113 Log.w(TAG, "Failed to enable network " + config.SSID);
116 Log.w(TAG, "Unable to add network " + config.SSID);
120 private static WifiConfiguration changeNetworkCommon(WifiParsedResult wifiResult) {
121 WifiConfiguration config = new WifiConfiguration();
122 config.allowedAuthAlgorithms.clear();
123 config.allowedGroupCiphers.clear();
124 config.allowedKeyManagement.clear();
125 config.allowedPairwiseCiphers.clear();
126 config.allowedProtocols.clear();
127 // Android API insists that an ascii SSID must be quoted to be correctly handled.
128 config.SSID = quoteNonHex(wifiResult.getSsid());
129 config.hiddenSSID = wifiResult.isHidden();
133 // Adding a WEP network
134 private static void changeNetworkWEP(WifiManager wifiManager, WifiParsedResult wifiResult) {
135 WifiConfiguration config = changeNetworkCommon(wifiResult);
136 config.wepKeys[0] = quoteNonHex(wifiResult.getPassword(), 10, 26, 58);
137 config.wepTxKeyIndex = 0;
138 config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
139 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
140 config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
141 config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
142 config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
143 config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
144 updateNetwork(wifiManager, config);
147 // Adding a WPA or WPA2 network
148 private static void changeNetworkWPA(WifiManager wifiManager, WifiParsedResult wifiResult) {
149 WifiConfiguration config = changeNetworkCommon(wifiResult);
150 // Hex passwords that are 64 bits long are not to be quoted.
151 config.preSharedKey = quoteNonHex(wifiResult.getPassword(), 64);
152 config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
153 config.allowedProtocols.set(WifiConfiguration.Protocol.WPA); // For WPA
154 config.allowedProtocols.set(WifiConfiguration.Protocol.RSN); // For WPA2
155 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
156 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
157 config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
158 config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
159 config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
160 config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
161 updateNetwork(wifiManager, config);
164 // Adding an open, unsecured network
165 private static void changeNetworkUnEncrypted(WifiManager wifiManager, WifiParsedResult wifiResult) {
166 WifiConfiguration config = changeNetworkCommon(wifiResult);
167 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
168 updateNetwork(wifiManager, config);
171 private static Integer findNetworkInExistingConfig(WifiManager wifiManager, String ssid) {
172 Iterable<WifiConfiguration> existingConfigs = wifiManager.getConfiguredNetworks();
173 for (WifiConfiguration existingConfig : existingConfigs) {
174 String existingSSID = existingConfig.SSID;
175 if (existingSSID != null && existingSSID.equals(ssid)) {
176 return existingConfig.networkId;
182 private static String quoteNonHex(String value, int... allowedLengths) {
183 return isHexOfLength(value, allowedLengths) ? value : convertToQuotedString(value);
187 * Encloses the incoming string inside double quotes, if it isn't already quoted.
188 * @param s the input string
189 * @return a quoted string, of the form "input". If the input string is null, it returns null
192 private static String convertToQuotedString(String s) {
193 if (s == null || s.isEmpty()) {
196 // If already quoted, return as-is
197 if (s.charAt(0) == '"' && s.charAt(s.length() - 1) == '"') {
200 return '\"' + s + '\"';
204 * @param value input to check
205 * @param allowedLengths allowed lengths, if any
206 * @return true if value is a non-null, non-empty string of hex digits, and if allowed lengths are given, has
209 private static boolean isHexOfLength(CharSequence value, int... allowedLengths) {
210 if (value == null || !HEX_DIGITS.matcher(value).matches()) {
213 if (allowedLengths.length == 0) {
216 for (int length : allowedLengths) {
217 if (value.length() == length) {