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.app.AlertDialog;
23 import android.content.ActivityNotFoundException;
24 import android.content.Intent;
25 import android.content.IntentFilter;
26 import android.net.ConnectivityManager;
27 import android.net.Uri;
28 import android.net.wifi.WifiConfiguration;
29 import android.net.wifi.WifiManager;
30 import android.os.Bundle;
31 import android.util.Log;
32 import android.widget.TextView;
34 import com.google.zxing.client.android.Intents;
35 import com.google.zxing.client.android.R;
38 * A new activity showing the progress of Wifi connection
40 * TODO(viki): Tell the user when the network is not available here
41 * TODO(viki): Incorrect password, could not connect, give an error
43 * @author Vikram Aggarwal
45 public class WifiActivity extends Activity {
47 private static final String TAG = WifiActivity.class.getSimpleName();
49 private WifiManager wifiManager;
50 private TextView statusView;
51 private ConnectedReceiver connectedReceiver;
53 public enum NetworkType {
54 NETWORK_WEP, NETWORK_WPA, NETWORK_NOPASS, NETWORK_INVALID,
57 private int changeNetwork(NetworkSetting setting) {
58 // All the ways this can be wrong:
60 // If the SSID is empty, throw an error and return
61 if (setting.getSsid() == null || setting.getSsid().length() == 0) {
62 return doError(R.string.wifi_ssid_missing);
64 // If the network type is invalid
65 if (setting.getNetworkType() == NetworkType.NETWORK_INVALID){
66 return doError(R.string.wifi_type_incorrect);
69 // If the password is empty, this is an unencrypted network
70 if (setting.getPassword() == null || setting.getPassword().length() == 0 ||
71 setting.getNetworkType() == null ||
72 setting.getNetworkType() == NetworkType.NETWORK_NOPASS) {
73 return changeNetworkUnEncrypted(setting);
75 if (setting.getNetworkType() == NetworkType.NETWORK_WPA) {
76 return changeNetworkWPA(setting);
78 return changeNetworkWEP(setting);
82 private int doError(int resource_string) {
83 statusView.setText(resource_string);
87 private WifiConfiguration changeNetworkCommon(NetworkSetting input){
88 statusView.setText("Creating settings...");
89 Log.d(TAG, "Adding new configuration: \nSSID: " + input.getSsid() + "\nType: " + input.getNetworkType());
90 WifiConfiguration config = new WifiConfiguration();
92 config.allowedAuthAlgorithms.clear();
93 config.allowedGroupCiphers.clear();
94 config.allowedKeyManagement.clear();
95 config.allowedPairwiseCiphers.clear();
96 config.allowedProtocols.clear();
98 // Android API insists that an ascii SSID must be quoted to be correctly handled.
99 config.SSID = NetworkUtil.convertToQuotedString(input.getSsid());
100 config.hiddenSSID = true;
104 private int requestNetworkChange(WifiConfiguration config){
105 statusView.setText(R.string.wifi_changing_network);
106 return updateNetwork(config, false);
109 // Adding a WEP network
110 private int changeNetworkWEP(NetworkSetting input) {
111 WifiConfiguration config = changeNetworkCommon(input);
112 if (NetworkUtil.isHexWepKey(input.getPassword())) {
113 config.wepKeys[0] = input.getPassword();
115 config.wepKeys[0] = NetworkUtil.convertToQuotedString(input.getPassword());
117 config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
118 config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
119 config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
120 config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
121 config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
122 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
123 config.wepTxKeyIndex = 0;
124 return requestNetworkChange(config);
127 // Adding a WPA or WPA2 network
128 private int changeNetworkWPA(NetworkSetting input) {
129 WifiConfiguration config = changeNetworkCommon(input);
130 config.preSharedKey = NetworkUtil.convertToQuotedString(input.getPassword());
131 config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
132 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
134 config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
136 config.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
137 return requestNetworkChange(config);
140 // Adding an open, unsecured network
141 private int changeNetworkUnEncrypted(NetworkSetting input){
142 WifiConfiguration config = changeNetworkCommon(input);
143 Log.d(TAG, "Empty password prompting a simple account setting");
144 config.wepKeys[0] = "";
145 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
146 config.wepTxKeyIndex = 0;
147 return requestNetworkChange(config);
151 * If the given ssid name exists in the settings, then change its password to the one given here, and save
154 private WifiConfiguration findNetworkInExistingConfig(String ssid){
155 List <WifiConfiguration> existingConfigs = wifiManager.getConfiguredNetworks();
156 for (WifiConfiguration existingConfig : existingConfigs) {
157 if (existingConfig.SSID.equals(ssid)) {
158 return existingConfig;
165 protected void onCreate(Bundle savedInstanceState) {
166 super.onCreate(savedInstanceState);
168 Intent intent = getIntent();
169 if (intent == null || (!intent.getAction().equals(Intents.WifiConnect.ACTION))) {
174 String ssid = intent.getStringExtra(Intents.WifiConnect.SSID);
175 String password = intent.getStringExtra(Intents.WifiConnect.PASSWORD);
176 String networkType = intent.getStringExtra(Intents.WifiConnect.TYPE);
177 setContentView(R.layout.network);
178 statusView = (TextView) findViewById(R.id.networkStatus);
180 // TODO(vikrama): Error checking here, to ensure ssid exists.
181 NetworkType networkT;
182 if (networkType.equals("WPA")) {
183 networkT = NetworkType.NETWORK_WPA;
184 } else if (networkType.equals("WEP")) {
185 networkT = NetworkType.NETWORK_WEP;
186 } else if (networkType.equals("nopass")) {
187 networkT = NetworkType.NETWORK_NOPASS;
189 // Got an incorrect network type. Give an error
190 doError(R.string.wifi_type_incorrect);
194 // This is not available before onCreate
195 wifiManager = (WifiManager) this.getSystemService(WIFI_SERVICE);
197 // So we know when the network changes
198 connectedReceiver = new ConnectedReceiver(this, statusView);
199 registerReceiver(connectedReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
201 if (password == null) {
204 Log.d(TAG, "Adding new configuration: \nSSID: " + ssid + "Type: " + networkT);
205 NetworkSetting setting = new NetworkSetting(ssid, password, networkT);
206 changeNetwork(setting);
210 protected void onDestroy() {
211 if (connectedReceiver != null) {
212 unregisterReceiver(connectedReceiver);
213 connectedReceiver = null;
219 * Update the network: either create a new network or modify an existing network
220 * @param config the new network configuration
221 * @param disableOthers true if other networks must be disabled
222 * @return network ID of the connected network.
224 private int updateNetwork(WifiConfiguration config, boolean disableOthers){
226 if (findNetworkInExistingConfig(config.SSID) == null){
227 statusView.setText(R.string.wifi_creating_network);
228 networkId = wifiManager.addNetwork(config);
230 statusView.setText(R.string.wifi_modifying_network);
231 networkId = wifiManager.updateNetwork(config);
233 if (networkId == -1 || !wifiManager.enableNetwork(networkId, disableOthers)) {
236 wifiManager.saveConfiguration();