1. 程式人生 > >Android WIFI 配置、連線

Android WIFI 配置、連線

在RK3188板卡上實現Wifi配置與連線,在網上搜索了一些資料瞭解到wifi連線流程,下面是從第一次刷機後的連線wifi流程

1、判斷wifi是否啟動如果沒啟動則開啟wifi

2、掃描wifi根據要連線的wifi名稱檢索出想要的掃描結果

3、掃描結果判斷該名稱wifi的加密型別

4、根據wifi加密型別建立wifi配置

5、將wifi配置新增都wiifi配置列表,得到該配置的唯一ID;這部很重要

6、根據得到的配置ID進行連線wifi

先貼出自己實現的一個Wifi輔助類

package com.midea.test.factory.wifi;

import java.util.List;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.AuthAlgorithm;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiManager;

public class WifiHelper {
	
	public static final int SECURITY_NONE = 0;
	public static final int SECURITY_WEP = 1;
	public static final int SECURITY_PSK = 2; // WPA、WPA2、WPA_WPA2
	public static final int SECURITY_EAP = 3;
	
	
	public static void startScan(Context context){
		WifiManager manager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
		manager.startScan();
	}
	
	public static List<ScanResult> getScanResults(Context context){
		WifiManager manager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
		return manager.getScanResults();
	}
	public static boolean isWifiOpen(Context context){
		WifiManager manager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
		return manager.isWifiEnabled();
	}
	public static void setWifiEnabled(Context context,boolean isEnabled){
		WifiManager manager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
		manager.setWifiEnabled(isEnabled);	//是否開啟需監聽廣播 WIFI_STATE_CHANGED_ACTION
	}
    public static int updateWifiConfiguration(Context context,WifiConfiguration configuration){
    	WifiManager manager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    	return manager.updateNetwork(configuration);
    }
    public static boolean isWifiConnected(Context context)
    {
        ConnectivityManager connectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
        
        NetworkInfo[] networkInfos = connectivityManager.getAllNetworkInfo();
        if(networkInfos == null){
        	return false;
        }
        for(int i =0; i < networkInfos.length; i ++){
        	if(networkInfos[i].getState()== NetworkInfo.State.CONNECTED){
        		return true;
        	}
        }
     
        return false ;
    }
    
    public static WifiConfiguration checkWifiConfiguration(Context context,String ssid){
    	WifiManager manager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    	
    	List<WifiConfiguration> configurations = manager.getConfiguredNetworks();
    	if(configurations == null){
    		return null;
    	}
    	for(WifiConfiguration configuration :configurations){
    		if(configuration.SSID.equals(ssid)){
    			return configuration;
    		}
    	}
    	return null;
    }
    
    public static  int getSecurity(ScanResult result) {
		if (result.capabilities.contains("WEP")) {
			return SECURITY_WEP;
		} else if (result.capabilities.contains("PSK")) {
			return SECURITY_PSK;
		} else if (result.capabilities.contains("EAP")) {
			return SECURITY_EAP;
		}
		return SECURITY_NONE;
	}
    
    public static String convertToQuotedString(String string) {
        return "\"" + string + "\"";
    }
    
  //from com.android.settings.wifi.WifiConfigController
    /**
     * 這裡直接是閱讀系統設定裡面的wifi配置
     * 其實這裡可以閱讀以下WifiConfiguration,裡面關於wifi的加密引數
     * @param accessPointSecurity
     * @param ssid
     * @param password
     * @return
     */
  	public static WifiConfiguration getConfig(int accessPointSecurity, String ssid,
  			String password) {

  		WifiConfiguration config = new WifiConfiguration();
  		config.SSID = convertToQuotedString(ssid);
  		config.hiddenSSID = true;
  		switch (accessPointSecurity) {
  		case SECURITY_NONE:
  			config.allowedKeyManagement.set(KeyMgmt.NONE);
  			break;

  		case SECURITY_WEP:
  			config.allowedKeyManagement.set(KeyMgmt.NONE);
  			config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
  			config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
  			int length = password.length();
  			// WEP-40, WEP-104, and 256-bit WEP (WEP-232?)
  			if ((length == 10 || length == 26 || length == 58)
  					&& password.matches("[0-9A-Fa-f]*")) {
  				config.wepKeys[0] = password;
  			} else {
  				config.wepKeys[0] = '"' + password + '"';
  			}
  			break;

  		case SECURITY_PSK:
  			config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
  			if (password.length() != 0) {
  				if (password.matches("[0-9A-Fa-f]{64}")) {
  					config.preSharedKey = password;
  				} else {
  					config.preSharedKey = '"' + password + '"';
  				}
  			}
  			break;

  		case SECURITY_EAP:
  			//EAP暫時還沒不完整
  			 config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
             config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
  			break;
  		default:
  			return null;
  		}

  		return config;
  	}
  	
  	public static int addWifiConfiguration(Context context,WifiConfiguration configuration){
  		WifiManager manager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
  		return manager.addNetwork(configuration);
  	}
  	
  	public static void connectWifi(Context context,int networkId){
  		WifiManager manager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
  		manager.enableNetwork(networkId, true);
  	}

}

下面程式碼是實現 搜尋 配置 連線的過程。主要流程是

1、如果沒開啟Wifi就開啟Wifi,然後在廣播“WifiManager.WIFI_STATE_CHANGED_ACTION”去掃描wifi熱點(當然這裡不夠嚴格,應該還要判斷wifi狀態是否可用);

如果wifi是開啟狀態就直接掃描,掃描wifi會觸發“WifiManager.NETWORK_STATE_CHANGED_ACTION”廣播,在這個廣播裡面獲取WifiInfo後可以判斷要連線的wifi名稱是否存在,如果存在則WIFI是已經連線的。

2、啟動掃描後不是立即返回掃描列表的,可以看看API解釋

/**
     * Request a scan for access points. Returns immediately. The availability
     * of the results is made known later by means of an asynchronous event sent
     * on completion of the scan.
     * @return {@code true} if the operation succeeded, i.e., the scan was initiated
     */
    public boolean startScan() {
        try {
            final WorkSource workSource = null;
            mService.startScan(workSource);
            return true;
        } catch (RemoteException e) {
            return false;
        }
    }
英語不好就用有道翻譯一下Request a scan for access points. Returns immediately. The availability of the results is made knownlater by means of an asynchronous event sent on completion of the scan.主要看到這個幾個紅字便可知道非同步返回,需要監聽廣播“WifiManager.SCAN_RESULTS_AVAILABLE_ACTION”

3、掃描列表出來後需要或者要連線的wifi加密方式,以下是摘自系統設定的程式碼

    public static  int getSecurity(ScanResult result) {
		if (result.capabilities.contains("WEP")) {
			return SECURITY_WEP;
		} else if (result.capabilities.contains("PSK")) {
			return SECURITY_PSK;
		} else if (result.capabilities.contains("EAP")) {
			return SECURITY_EAP;
		}
		return SECURITY_NONE;
	}
其實這裡的PSK是包含WPA、WPA2、WPA_WPA2三種加密方式(可以閱讀系統設定的WifiConfigController.java)

4、得到要連線wifi的加密方式後這時需建立wifi配置,程式碼如下也是摘自系統設定的

//from com.android.settings.wifi.WifiConfigController
    /**
     * 這裡直接是閱讀系統設定裡面的wifi配置
     * 其實這裡可以閱讀以下WifiConfiguration,裡面關於wifi的加密引數
     * @param accessPointSecurity
     * @param ssid
     * @param password
     * @return
     */
  	public static WifiConfiguration getConfig(int accessPointSecurity, String ssid,
  			String password) {

  		WifiConfiguration config = new WifiConfiguration();
  		config.SSID = convertToQuotedString(ssid);
  		config.hiddenSSID = true;
  		switch (accessPointSecurity) {
  		case SECURITY_NONE:
  			config.allowedKeyManagement.set(KeyMgmt.NONE);
  			break;

  		case SECURITY_WEP:
  			config.allowedKeyManagement.set(KeyMgmt.NONE);
  			config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
  			config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
  			int length = password.length();
  			// WEP-40, WEP-104, and 256-bit WEP (WEP-232?)
  			if ((length == 10 || length == 26 || length == 58)
  					&& password.matches("[0-9A-Fa-f]*")) {
  				config.wepKeys[0] = password;
  			} else {
  				config.wepKeys[0] = '"' + password + '"';
  			}
  			break;

  		case SECURITY_PSK:
  			config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
  			if (password.length() != 0) {
  				if (password.matches("[0-9A-Fa-f]{64}")) {
  					config.preSharedKey = password;
  				} else {
  					config.preSharedKey = '"' + password + '"';
  				}
  			}
  			break;

  		case SECURITY_EAP:
  			//EAP暫時還沒不完整
  			 config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
             config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
  			break;
  		default:
  			return null;
  		}

  		return config;
  	}

5、配置好後需要新增到wifi配置列表得到配置的id
 manager.addNetwork(configuration);
6、通過配置的ID提交連線,連線的過程也是非同步的,需要監聽廣播“WifiManager.NETWORK_STATE_CHANGED_ACTION”,在這個廣播裡面獲取WifiInfo後可以判斷要連線的wifi名稱是否存在,如果存在則WIFI是已經連線的。

以上只是大概的流程,還需嚴格控制。