WiFiConnecter.java 6.89 KB
package com.sunvote.xpadapp.utils;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.Message;

import com.sunvote.util.LogUtil;
import com.sunvote.util.StringUtils;

import java.util.List;

public class WiFiConnecter {
	// Combo scans can take 5-6s to complete
	private static final int WIFI_RESCAN_INTERVAL_MS = 15 * 1000;

	static final int SECURITY_NONE = 0;
	static final int SECURITY_WEP = 1;
	static final int SECURITY_PSK = 2;
	static final int SECURITY_EAP = 3;
	private static final String TAG = WiFiConnecter.class.getSimpleName();
	public static final int MAX_TRY_COUNT = 3;

	private Context mContext;
	private WifiManager mWifiManager;

	private final IntentFilter mFilter;
	private final BroadcastReceiver mReceiver;
	private final Scanner mScanner;
	private ActionListener mListener;
	private String mSsid;
	private String mPassword;
	private String security = "WPA";

	private boolean isRegistered;
	private boolean isActiveScan;
	private boolean bySsidIgnoreCase;

	public WiFiConnecter(Context context) {
		this.mContext = context;
		mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);

		mFilter = new IntentFilter();
		mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
		mFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
		mFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);
		mFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
		mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);

		mReceiver = new BroadcastReceiver() {
			@Override
			public void onReceive(Context context, Intent intent) {
				handleEvent(context, intent);
			}
		};

		context.registerReceiver(mReceiver, mFilter);
		isRegistered = true;
		bySsidIgnoreCase = true;
		mScanner = new Scanner();
	}

	public void connect(String ssid, String password,ActionListener listener){
		connect(ssid,password,security,listener);
	}

	/**
	 * Connect to a WiFi with the given ssid and password
	 *
	 * @param ssid
	 * @param password
	 * @param listener : for callbacks on start or success or failure. Can be null.
	 */
	public void connect(String ssid, String password, String security,ActionListener listener) {
		this.mListener = listener;
		this.mSsid = ssid;
		this.mPassword = password;
		this.security = security;

		if (listener != null) {
			listener.onStarted(ssid);
		}

		WifiInfo info = mWifiManager.getConnectionInfo();
		String quotedString = StringUtils.convertToQuotedString(mSsid);
		boolean ssidEquals = bySsidIgnoreCase ? quotedString.equalsIgnoreCase(info.getSSID())
				: quotedString.equals(info.getSSID());
		if (ssidEquals) {
			if (listener != null) {
				listener.onSuccess(info);
				listener.onFinished(true);
			}
			return;
		}

		mScanner.forceScan();
	}

	private void handleEvent(Context context, Intent intent) {
		String action = intent.getAction();
		//An access point scan has completed, and results are available from the supplicant.
		if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action) && isActiveScan) {
//			connectWifi();
			//Broadcast intent action indicating that the state of Wi-Fi connectivity has changed.
		} else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
			NetworkInfo mInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
			WifiInfo mWifiInfo = mWifiManager.getConnectionInfo();
			//ssid equals&&connected
			if (mWifiInfo != null && mInfo.isConnected() && mWifiInfo.getSSID() != null) {
				String quotedString = StringUtils.convertToQuotedString(mSsid);
				String currentSSid = mWifiInfo.getSSID();
				currentSSid = StringUtils.convertToQuotedString(currentSSid);
				boolean ssidEquals = bySsidIgnoreCase ? quotedString.equalsIgnoreCase(currentSSid)
						: quotedString.equals(mWifiInfo.getSSID());
				if (ssidEquals) {
					if (mListener != null) {
						mListener.onSuccess(mWifiInfo);
						mListener.onFinished(true);
					}
					onPause();
				}

			}
		}
	}

	private boolean connectWifi() {
		List<ScanResult> results = mWifiManager.getScanResults();
		if(results != null && results.size() > 0) {
			LogUtil.i(TAG,"connectWifi for scan");
			for (ScanResult result : results) {
				//1.scan dest of ssid
				String quotedString = StringUtils.convertToQuotedString(mSsid);
				String quotedSSID = StringUtils.convertToQuotedString(result.SSID);
				boolean ssidEquals = bySsidIgnoreCase ? quotedString.equalsIgnoreCase(quotedSSID)
						: quotedString.equals(quotedSSID);
				if (ssidEquals) {
					mScanner.pause();
					LogUtil.i(TAG,"connectWifi for scan ,sure");
					if (!WiFi.connectToNewNetwork(mWifiManager, result, mPassword)) {
						if (mListener != null) {
							mListener.onFailure();
							mListener.onFinished(false);
						}
						onPause();
						return false;
					}
					return true;
				}
			}
		}else{
			if (!WiFi.connectToNewNetwork(mWifiManager, security,mSsid, mPassword)) {
				if (mListener != null) {
					mListener.onFailure();
					mListener.onFinished(false);
				}
				onPause();
				return false;
			}
		}
		return true;
	}

	public void onPause() {
		if (isRegistered) {
			mContext.unregisterReceiver(mReceiver);
			isRegistered = false;
		}
		mScanner.pause();
	}

	public void onResume() {
		if (!isRegistered) {
			mContext.registerReceiver(mReceiver, mFilter);
			isRegistered = true;
		}
		mScanner.resume();
	}

	private class Scanner extends Handler {
		private int mRetry = 0;

		void resume() {
			if (!hasMessages(0)) {
				sendEmptyMessage(0);
			}
		}

		void forceScan() {
			removeMessages(0);
			sendEmptyMessage(0);
		}

		void pause() {
			mRetry = 0;
			isActiveScan = false;
			removeMessages(0);
		}

		@Override
		public void handleMessage(Message message) {
			if (mRetry < MAX_TRY_COUNT) {
				mRetry++;
				isActiveScan = true;
				//1.打开Wifi
				if (!mWifiManager.isWifiEnabled()) {
					boolean ret = mWifiManager.setWifiEnabled(true);
					if(!ret){
						isActiveScan = false;
						if (mListener != null) {
							mListener.onFailure();
							mListener.onFinished(false);
						}
						onPause();
						return;
					}
				}
				if(!connectWifi()){
					return;
				}
			} else {
				mRetry = 0;
				isActiveScan = false;
				if (mListener != null) {
					mListener.onFailure();
					mListener.onFinished(false);
				}
				onPause();
				return;
			}
			sendEmptyMessageDelayed(0, WIFI_RESCAN_INTERVAL_MS);
		}
	}

	public interface ActionListener {

		/**
		 * The operation started
		 *
		 * @param ssid
		 */
		public void onStarted(String ssid);

		/**
		 * The operation succeeded
		 *
		 * @param info
		 */
		public void onSuccess(WifiInfo info);

		/**
		 * The operation failed
		 */
		public void onFailure();

		/**
		 * The operation finished
		 *
		 * @param isSuccessed
		 */
		public void onFinished(boolean isSuccessed);
	}
}