package com.almalence.sony.cameraremote.utils;
import java.util.ArrayList;
import java.util.List;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.util.Log;
public class WifiHandler {
private Context mContext;
private WifiManager mWifiManager;
private WifiInfo lastWifiConnected;
private NetworkInfo.State cameraWifiState;
private List<WifiListener> listeners;
public WifiHandler(Context context) {
this.mContext = context;
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
listeners = new ArrayList<WifiListener>();
cameraWifiState = State.UNKNOWN;
}
public void checkForConnection() {
cameraWifiState = State.DISCONNECTED;
WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
if(wifiInfo != null) {
String ssid = parseSSID(wifiInfo.getSSID());
if(isSonyCameraSSID(ssid)) {
// Don't need to check more, camera is already connected
connected(ssid);
return;
}
}
for(WifiListener listener : listeners) {
listener.onWifiStartScan();
}
mContext.registerReceiver(scanResultsBroadcastReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
mWifiManager.startScan();
}
public void createIfNeededThenConnectToWifi(String networkSSID, String networkPassword) {
mWifiManager.setWifiEnabled(true);
int netId = -1;
List<WifiConfiguration> list = mWifiManager.getConfiguredNetworks();
if(list != null) {
for( WifiConfiguration i : list ) {
// In the case of network is already registered
if(i.SSID != null && i.SSID.equals("\"" + networkSSID + "\"")) {
// In case password changed since last time
i.preSharedKey = "\""+ networkPassword +"\"";
mWifiManager.saveConfiguration();
netId = i.networkId;
break;
}
}
}
// In the case of network is not registered create it and join it
if(netId == -1) {
netId = createWPAWifi(networkSSID, networkPassword);
}
connectToNetworkId(netId);
}
public void connectToNetworkId(int netId) {
List<WifiConfiguration> configuredNetworks = mWifiManager.getConfiguredNetworks();
for(WifiConfiguration wc : configuredNetworks) {
if(wc.networkId != netId) {
continue;
}
cameraWifiState = State.CONNECTING;
WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
if(wifiInfo != null) {
String ssid = parseSSID(mWifiManager.getConnectionInfo().getSSID());
if(!isSonyCameraSSID(ssid)) {
lastWifiConnected = mWifiManager.getConnectionInfo();
}
}
// Connect only if network id exist
mWifiManager.enableNetwork(netId, true);
for(WifiListener listener : listeners) {
listener.onWifiConnecting(wc.SSID);
}
}
}
private int createWPAWifi(String networkSSID, String networkPassword) {
WifiConfiguration wc = new WifiConfiguration();
wc.SSID = "\"" + networkSSID + "\"";
wc.preSharedKey = "\""+ networkPassword +"\"";
wc.hiddenSSID = true;
wc.status = WifiConfiguration.Status.ENABLED;
wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
int netId = mWifiManager.addNetwork(wc);
mWifiManager.saveConfiguration();
return netId;
}
public void reconnectToLastWifi() {
if(lastWifiConnected != null) {
mWifiManager.enableNetwork(lastWifiConnected.getNetworkId(), true);
// Maybe remove comment on this line for more logic
//lastWifiConnected = null;
}
}
private static boolean isSonyCameraSSID(String ssid) {
return ssid != null && ssid.matches("^DIRECT-\\w{4}:.*$");
}
private WifiConfiguration getWifiConfigurationFromSSID(String SSID) {
List<WifiConfiguration> knownNetworks = mWifiManager.getConfiguredNetworks();
if(knownNetworks == null) {
return null;
}
for(WifiConfiguration net : knownNetworks) {
if(net.SSID != null && net.SSID.equals("\""+SSID+"\"")) {
return net;
}
}
return null;
}
public void addListener(WifiListener listener) {
if(listeners.contains(listener)) {
return;
}
listeners.add(listener);
}
public void removeListener(WifiListener listener) {
if(!listeners.contains(listener)) {
return;
}
listeners.remove(listener);
}
private void connected(String ssid) {
cameraWifiState = State.CONNECTED;
for(WifiListener listener : listeners) {
listener.onWifiConnected(ssid);
}
}
private void disconnected() {
cameraWifiState = State.DISCONNECTED;
for(WifiListener listener : listeners) {
listener.onWifiDisconnected();
}
}
private BroadcastReceiver wifiBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
NetworkInfo networkInfo = null;
try {
networkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
} catch (Exception e) {
e.printStackTrace();
return;
}
if(networkInfo == null || networkInfo.getType() != ConnectivityManager.TYPE_WIFI) {
return;
}
WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
NetworkInfo.State state = networkInfo.getState();
if(cameraWifiState == State.CONNECTED && state == State.DISCONNECTED) {
disconnected();
}
if(state == State.CONNECTED && wifiInfo != null) {
String ssid = parseSSID(wifiInfo.getSSID());
if(!isSonyCameraSSID(ssid)) {
return;
}
connected(ssid);
}
}
};
private BroadcastReceiver scanResultsBroadcastReceiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
List<WifiConfiguration> sonyCameraWifiConfiguration = new ArrayList<WifiConfiguration>();
List<ScanResult> sonyCameraScanResults = new ArrayList<ScanResult>();
List<ScanResult> results = mWifiManager.getScanResults();
for(ScanResult sr : results) {
if(!isSonyCameraSSID(sr.SSID)) {
continue;
}
sonyCameraScanResults.add(sr);
WifiConfiguration wc = getWifiConfigurationFromSSID(sr.SSID);
if(wc == null) {
continue;
}
sonyCameraWifiConfiguration.add(wc);
}
for(WifiListener listener : listeners) {
listener.onWifiScanFinished(sonyCameraScanResults, sonyCameraWifiConfiguration);
}
context.unregisterReceiver(scanResultsBroadcastReceiver);
}
};
public void register() {
final IntentFilter filters = new IntentFilter();
filters.addAction("android.net.wifi.WIFI_STATE_CHANGED");
filters.addAction("android.net.wifi.STATE_CHANGE");
mContext.registerReceiver(wifiBroadcastReceiver, filters);
}
public void unregister() {
try {
mContext.unregisterReceiver(wifiBroadcastReceiver);
mContext.unregisterReceiver(scanResultsBroadcastReceiver);
} catch (IllegalArgumentException e) { }
}
public State getCameraWifiState() {
return cameraWifiState;
}
private String parseSSID(String ssid) {
if(ssid != null && ssid.length() >= 2 && ssid.charAt(0) == '"' && ssid.charAt(ssid.length()-1) == '"') {
return ssid.substring(1, ssid.length()-1);
}
return ssid;
}
}