344e3fdb639e13fd377a204dbb68646476d2d00f
[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  * @author Vikram Aggarwal
38  */
39 public class WifiActivity extends Activity  {
40
41   private static final String TAG = WifiActivity.class.getSimpleName();
42
43   private WifiManager wifiManager;
44   private TextView statusView;
45   private ConnectedReceiver connectedReceiver;
46
47   public enum NetworkType {
48     NETWORK_WEP, NETWORK_WPA, NETWORK_NOPASS,
49   }
50
51   private int changeNetwork(NetworkSetting setting) {
52     // If the password is empty, this is an unencrypted network
53     if (setting.getPassword() == null || setting.getPassword().length() == 0 ||
54         setting.getNetworkType() == null ||
55         setting.getNetworkType() == NetworkType.NETWORK_NOPASS) {
56       return changeNetworkUnEncrypted(setting);
57     }
58     if (setting.getNetworkType() == NetworkType.NETWORK_WPA) {
59       return changeNetworkWPA(setting); 
60     } else {
61       return changeNetworkWEP(setting);
62     }
63   }
64
65   private WifiConfiguration changeNetworkCommon(NetworkSetting input){
66     statusView.setText("Creating settings...");
67     Log.d(TAG, "Adding new configuration: \nSSID: " + input.getSsid() + "\nType: " + input.getNetworkType());
68     WifiConfiguration config = new WifiConfiguration();
69
70     config.allowedAuthAlgorithms.clear();
71     config.allowedGroupCiphers.clear();
72     config.allowedKeyManagement.clear();
73     config.allowedPairwiseCiphers.clear();
74     config.allowedProtocols.clear();
75
76     // Android API insists that an ascii SSID must be quoted to be correctly handled.
77     config.SSID = NetworkUtil.convertToQuotedString(input.getSsid());   
78     config.hiddenSSID = true;
79     return config;
80   }
81
82   private int requestNetworkChange(WifiConfiguration config){
83     statusView.setText("Changing Network...");
84     return updateNetwork(config, false);
85   }
86
87   // Adding a WEP network
88   private int changeNetworkWEP(NetworkSetting input) {
89     WifiConfiguration config = changeNetworkCommon(input);
90     if (NetworkUtil.isHexWepKey(input.getPassword())) {
91       config.wepKeys[0] = input.getPassword();
92     } else {
93       config.wepKeys[0] = NetworkUtil.convertToQuotedString(input.getPassword());
94     }
95     config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
96     config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
97     config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
98     config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
99     config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
100     config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
101     config.wepTxKeyIndex = 0;
102     return requestNetworkChange(config);
103   }
104
105   // Adding a WPA or WPA2 network
106   private int changeNetworkWPA(NetworkSetting input) {
107     WifiConfiguration config = changeNetworkCommon(input);
108     config.preSharedKey = NetworkUtil.convertToQuotedString(input.getPassword());
109     config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
110     config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
111     // For WPA
112     config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
113     // For WPA2
114     config.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
115     return requestNetworkChange(config);
116   }
117
118   // Adding an open, unsecured network
119   private int changeNetworkUnEncrypted(NetworkSetting input){
120     WifiConfiguration config = changeNetworkCommon(input);
121     Log.d(TAG, "Empty password prompting a simple account setting");
122     config.wepKeys[0] = "";
123     config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
124     config.wepTxKeyIndex = 0;
125     return requestNetworkChange(config);
126   }
127
128   /**
129    * If the given ssid name exists in the settings, then change its password to the one given here, and save
130    * @param ssid
131    */
132   private WifiConfiguration findNetworkInExistingConfig(String ssid){
133     List <WifiConfiguration> existingConfigs = wifiManager.getConfiguredNetworks();
134     for (WifiConfiguration existingConfig : existingConfigs) {
135       if (existingConfig.SSID.equals(ssid)) {
136         return existingConfig;
137       }
138     }
139     return null;
140   }
141
142   @Override
143   protected void onCreate(Bundle savedInstanceState) {
144     super.onCreate(savedInstanceState);
145
146     Intent intent = getIntent();
147     if (intent == null || (!intent.getAction().equals(Intents.WifiConnect.ACTION))) {
148       finish();
149       return;
150     }
151
152     String ssid = intent.getStringExtra(Intents.WifiConnect.SSID);
153     String password = intent.getStringExtra(Intents.WifiConnect.PASSWORD);
154     String networkType = intent.getStringExtra(Intents.WifiConnect.TYPE);
155
156     // TODO(vikrama): Error checking here, to ensure ssid exists.
157     NetworkType networkT;
158     if (networkType.contains("WPA")) {
159       networkT = NetworkType.NETWORK_WPA;
160     } else if (networkType.contains("WEP")) {
161       networkT = NetworkType.NETWORK_WEP;
162     } else if (networkType.contains("nopass")) {
163      networkT = NetworkType.NETWORK_NOPASS; 
164     } else {
165       // Got an incorrect network type
166       finish();
167       return;
168     }
169
170     setContentView(R.layout.network);
171     statusView = (TextView) findViewById(R.id.networkStatus);
172     // This is not available before onCreate
173     wifiManager = (WifiManager) this.getSystemService(WIFI_SERVICE);
174
175     // So we know when the network changes
176     connectedReceiver = new ConnectedReceiver(this, statusView);
177     registerReceiver(connectedReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
178
179     if (password == null) {
180       password = "";
181     }
182     Log.d(TAG, "Adding new configuration: \nSSID: " + ssid + "Type: " + networkT);
183     NetworkSetting setting = new NetworkSetting(ssid, password, networkT);
184     changeNetwork(setting);
185   }
186
187   @Override
188   protected void onDestroy() {
189     if (connectedReceiver != null) {
190       unregisterReceiver(connectedReceiver);
191       connectedReceiver = null;
192     }
193     super.onDestroy();
194   }
195
196   /**
197    * Update the network: either create a new network or modify an existing network
198    * @param config the new network configuration
199    * @param disableOthers true if other networks must be disabled
200    * @return network ID of the connected network.
201    */
202   private int updateNetwork(WifiConfiguration config, boolean disableOthers){
203     int networkId;
204     if (findNetworkInExistingConfig(config.SSID) == null){
205       statusView.setText("Creating network...");
206       networkId = wifiManager.addNetwork(config);
207     } else {
208       statusView.setText("Modifying network...");
209       networkId = wifiManager.updateNetwork(config);
210     }
211     if (networkId == -1 || !wifiManager.enableNetwork(networkId, disableOthers)) {
212       return -1;
213     }
214     wifiManager.saveConfiguration();
215     return networkId;
216   }
217 }