Android WiFi開發 (二)Wifi熱點

接着上一篇wifi的掃描連接等,這一篇主要說一下手機開啓Wifi熱點。

demo的下載地址會在最下面貼出來。

圖片:

       

1 創建WIFI熱點

經測試開啓wifi熱點(無祕密,wpa安全類型,wpa2安全類型)都可以正常開啓並使用。

需要注意的是wifi和wifi熱點不能同時打開,也就是連接wifi的時候,開啓熱點需要先將wifi關閉纔可以。

用到的主要代碼:

package com.vn.wifitest.utils;


import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.util.Log;

public class WifiAPUtil {
    private static final String TAG = "WifiAPUtil";
    public final static boolean DEBUG = true;

    public static final int MESSAGE_AP_STATE_ENABLED = 1;
    public static final int MESSAGE_AP_STATE_FAILED = 2;
	//默認wifi祕密
    private static final String DEFAULT_AP_PASSWORD = "12345678";	
    private static WifiAPUtil sInstance;
    private static Handler mHandler;
    private static Context mContext;
    private WifiManager mWifiManager;
	//監聽wifi熱點的狀態變化
    public static final String WIFI_AP_STATE_CHANGED_ACTION = "android.net.wifi.WIFI_AP_STATE_CHANGED";
    public static final String EXTRA_WIFI_AP_STATE = "wifi_state";
    public static int WIFI_AP_STATE_DISABLING = 10;
    public static int WIFI_AP_STATE_DISABLED = 11;
    public static int WIFI_AP_STATE_ENABLING = 12;
    public static int WIFI_AP_STATE_ENABLED = 13;
    public static int WIFI_AP_STATE_FAILED = 14;
	public enum WifiSecurityType {
		WIFICIPHER_NOPASS, WIFICIPHER_WPA, WIFICIPHER_WEP, WIFICIPHER_INVALID, WIFICIPHER_WPA2
	}
	private WifiAPUtil(Context context) {
		if(DEBUG) Log.d(TAG,"WifiAPUtils construct"); 
		mContext = context;
		mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
		IntentFilter filter = new IntentFilter();
		filter.addAction(WIFI_AP_STATE_CHANGED_ACTION);
		context.registerReceiver(mWifiStateBroadcastReceiver, filter);
	}
	protected void finalize() {
		if(DEBUG) Log.d(TAG,"finalize");
		mContext.unregisterReceiver(mWifiStateBroadcastReceiver);

}
	public static WifiAPUtil getInstance(Context c) {
		if (null == sInstance)
		    sInstance = new WifiAPUtil(c);
		return sInstance;
	}

	public boolean turnOnWifiAp(String str, String password,WifiSecurityType Type) {
		String ssid = str;
		//配置熱點信息。
		WifiConfiguration wcfg = new WifiConfiguration();
		wcfg.SSID = new String(ssid);
		wcfg.networkId = 1;
		wcfg.allowedAuthAlgorithms.clear();
		wcfg.allowedGroupCiphers.clear();
		wcfg.allowedKeyManagement.clear();
		wcfg.allowedPairwiseCiphers.clear();
		wcfg.allowedProtocols.clear();
		
		if(Type == WifiSecurityType.WIFICIPHER_NOPASS) {
			if(DEBUG)Log.d(TAG, "wifi ap----no password");
			wcfg.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN, true);
			wcfg.wepKeys[0] = "";    
			wcfg.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);    
			wcfg.wepTxKeyIndex = 0;
		} else if(Type == WifiSecurityType.WIFICIPHER_WPA) {
			if(DEBUG)Log.d(TAG, "wifi ap----wpa");
			//密碼至少8位,否則使用默認密碼
			if(null != password && password.length() >= 8){
				wcfg.preSharedKey = password;
			} else {
				wcfg.preSharedKey = DEFAULT_AP_PASSWORD;
			}
			wcfg.hiddenSSID = false;       
			wcfg.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);       
			wcfg.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);                             
			wcfg.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);     
			//wcfg.allowedKeyManagement.set(4);
			wcfg.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);                        
			wcfg.allowedProtocols.set(WifiConfiguration.Protocol.WPA);      
			wcfg.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);    
			wcfg.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);    
		} else if(Type == WifiSecurityType.WIFICIPHER_WPA2) {
			if(DEBUG)Log.d(TAG, "wifi ap---- wpa2");
			//密碼至少8位,否則使用默認密碼
			if(null != password && password.length() >= 8){
				wcfg.preSharedKey = password;
			} else {
				wcfg.preSharedKey = DEFAULT_AP_PASSWORD;
			}     
			wcfg.hiddenSSID = true;       
			wcfg.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);       
			wcfg.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);                             
			wcfg.allowedKeyManagement.set(4);     
			//wcfg.allowedKeyManagement.set(4);
			wcfg.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);                        
			wcfg.allowedProtocols.set(WifiConfiguration.Protocol.WPA);      
			wcfg.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);    
			wcfg.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);    
		}		
		try {
			Method method = mWifiManager.getClass().getMethod("setWifiApConfiguration", 
									  wcfg.getClass());
			Boolean rt = (Boolean)method.invoke(mWifiManager, wcfg);
			if(DEBUG) Log.d(TAG, " rt = " + rt);
		} catch (NoSuchMethodException e) {
			Log.e(TAG, e.getMessage());
		} catch (IllegalArgumentException e) {
			Log.e(TAG, e.getMessage());
		} catch (IllegalAccessException e) {
			Log.e(TAG, e.getMessage());
		} catch (InvocationTargetException e) {
			Log.e(TAG, e.getMessage());
		}
		return setWifiApEnabled();
	}
	//獲取熱點狀態	
	public int getWifiAPState() {
		int state = -1;
		try {
			Method method2 = mWifiManager.getClass().getMethod("getWifiApState");
			state = (Integer) method2.invoke(mWifiManager);
		} catch (Exception e) {
			Log.e(TAG, e.getMessage());
		}
		if(DEBUG)Log.i("WifiAP", "getWifiAPState.state " + state);
		return state;
	}
	
	private boolean setWifiApEnabled() {		
		//開啓wifi熱點需要關閉wifi
		while(mWifiManager.getWifiState() != WifiManager.WIFI_STATE_DISABLED){
			mWifiManager.setWifiEnabled(false);
			try {
				Thread.sleep(200);
			} catch (Exception e) {
				Log.e(TAG, e.getMessage());
				return false;
			}
		}
		// 確保wifi 熱點關閉。
		while(getWifiAPState() != WIFI_AP_STATE_DISABLED){
			try {
			Method method1 = mWifiManager.getClass().getMethod("setWifiApEnabled",
					   WifiConfiguration.class, boolean.class);
            method1.invoke(mWifiManager, null, false);
		
				Thread.sleep(200);
			} catch (Exception e) {
				Log.e(TAG, e.getMessage());
					return false;
			}
		}
		
		//開啓wifi熱點
		try {
		Method method1 = mWifiManager.getClass().getMethod("setWifiApEnabled",
					   WifiConfiguration.class, boolean.class);
		method1.invoke(mWifiManager, null, true);		
				Thread.sleep(200);
			} catch (Exception e) {
				Log.e(TAG, e.getMessage());
					return false;
			}
		return true;
	}	
     //關閉WiFi熱點   
    public void closeWifiAp() {        
        if (getWifiAPState() != WIFI_AP_STATE_DISABLED) {    
            try {    
                Method method = mWifiManager.getClass().getMethod("getWifiApConfiguration");    
                method.setAccessible(true);    
                WifiConfiguration config = (WifiConfiguration) method.invoke(mWifiManager);    
                Method method2 = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);    
                method2.invoke(mWifiManager, config, false);    
            } catch (NoSuchMethodException e) {    
                e.printStackTrace();    
            } catch (IllegalArgumentException e) {    
                e.printStackTrace();    
            } catch (IllegalAccessException e) {    
                e.printStackTrace();    
            } catch (InvocationTargetException e) {    
                e.printStackTrace();    
            }    
        }   
    }  

	public void regitsterHandler(Handler handler){
		mHandler = handler;
	}
	public void unregitsterHandler(){
		mHandler = null;
	}
	//監聽wifi熱點狀態變化
    private BroadcastReceiver mWifiStateBroadcastReceiver = new BroadcastReceiver() {			
	    @Override
		public void onReceive(Context context, Intent intent) {
		if(DEBUG)Log.i(TAG,"WifiAPUtils onReceive: "+intent.getAction());
		if(WIFI_AP_STATE_CHANGED_ACTION.equals(intent.getAction())) {
		    int cstate = intent.getIntExtra(EXTRA_WIFI_AP_STATE, -1);
		    if(cstate == WIFI_AP_STATE_ENABLED) {
		    	if(mHandler != null){
		    		mHandler.sendEmptyMessage(MESSAGE_AP_STATE_ENABLED);			    
		    	}
		    }if(cstate == WIFI_AP_STATE_DISABLED  || cstate == WIFI_AP_STATE_FAILED) {
			if(mHandler != null)
			    mHandler.sendEmptyMessage(MESSAGE_AP_STATE_FAILED);
		    }
		}
	    }
	};
	//獲取熱點ssid
	public String getValidApSsid() {
		try {
			Method method = mWifiManager.getClass().getMethod("getWifiApConfiguration");
			WifiConfiguration configuration = (WifiConfiguration)method.invoke(mWifiManager);
			return configuration.SSID;	
		} catch (Exception e) {
				Log.e(TAG, e.getMessage());
				return null;
				}
	}
	//獲取熱點密碼
	public String getValidPassword(){
		try {
			Method method = mWifiManager.getClass().getMethod("getWifiApConfiguration");
			WifiConfiguration configuration = (WifiConfiguration)method.invoke(mWifiManager);
			return configuration.preSharedKey;	
		} catch (Exception e) {
				Log.e(TAG, e.getMessage());
				return null;
				}
	
	}
	//獲取熱點安全類型
	public int getValidSecurity(){
		WifiConfiguration configuration;
		try {
			Method method = mWifiManager.getClass().getMethod("getWifiApConfiguration");
			configuration = (WifiConfiguration)method.invoke(mWifiManager);
		} catch (Exception e) {
				Log.e(TAG, e.getMessage());
				return WifiSecurityType.WIFICIPHER_INVALID.ordinal();
				}
		
		if(DEBUG)Log.i(TAG,"getSecurity security="+configuration.allowedKeyManagement);
		if(configuration.allowedKeyManagement.get(KeyMgmt.NONE)) {
			return WifiSecurityType.WIFICIPHER_NOPASS.ordinal();
		}else if(configuration.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
			return WifiSecurityType.WIFICIPHER_WPA.ordinal();
		}else if(configuration.allowedKeyManagement.get(4)) { //4 means WPA2_PSK 
			return WifiSecurityType.WIFICIPHER_WPA2.ordinal();
		}
		return WifiSecurityType.WIFICIPHER_INVALID.ordinal();
	}
}

使用方法:

Activity生命週期中

//初始化WifiAPUtil類
WifiAPUtil.getInstance(getApplicationContext())
//註冊handler
WifiAPUtil.getInstance(this).regitsterHandler(mHandler);
//接收message,做處理
private Handler mHandler = new Handler(){
	public void handleMessage(Message msg) {
		switch (msg.what) {
			case WifiAPUtil.MESSAGE_AP_STATE_ENABLED:
	    		String ssid = WifiAPUtil.getInstance(WifiApActivity.this).getValidApSsid();
				String pw = WifiAPUtil.getInstance(WifiApActivity.this).getValidPassword();
				int security = WifiAPUtil.getInstance(WifiApActivity.this).getValidSecurity();
				mWifiApState.setText("wifi熱點開啓成功"+"\n"
						+"SSID = "+ssid+"\n"
						+"Password = "+pw +"\n"
						+"Security = "+security);
				break;
			case WifiAPUtil.MESSAGE_AP_STATE_FAILED:
				mWifiApState.setText("wifi熱點關閉");
				break;
			default:
				break;
		}
	}
};
在activity銷燬的時候

@Override
protected void onDestroy() {
	super.onDestroy();
	WifiAPUtil.getInstance(this).unregitsterHandler();
}
添加點擊事件

//開啓wifi熱點
WifiAPUtil.getInstance(WifiApActivity.this).turnOnWifiAp(ssid, password, mWifiType);

//關閉wifi熱點
WifiAPUtil.getInstance(WifiApActivity.this).closeWifiAp();

2 監聽熱點的狀態

當wifi熱點狀態發送變化,系統會發送廣播 android.net.wifi.WIFI_AP_STATE_CHANGED,所以我們只要註冊監聽這個廣播就可以了。

wifi ap狀態值。

public static final String EXTRA_WIFI_AP_STATE = "wifi_state";
public static int WIFI_AP_STATE_DISABLING = 10;
public static int WIFI_AP_STATE_DISABLED = 11;
public static int WIFI_AP_STATE_ENABLING = 12;
public static int WIFI_AP_STATE_ENABLED = 13;
public static int WIFI_AP_STATE_FAILED = 14;
動態註冊

public static final String WIFI_AP_STATE_CHANGED_ACTION = "android.net.wifi.WIFI_AP_STATE_CHANGED";
//註冊廣播接收者
IntentFilter filter = new IntentFilter();
filter.addAction(WIFI_AP_STATE_CHANGED_ACTION);
context.registerReceiver(mWifiStateBroadcastReceiver, filter);
廣播接收者

通過監聽wifiap狀態的變化,發送消息給相關activity

//監聽wifi熱點狀態變化
private BroadcastReceiver mWifiStateBroadcastReceiver = new BroadcastReceiver() {			
	@Override
        public void onReceive(Context context, Intent intent) {
	if(DEBUG)Log.i(TAG,"WifiAPUtils onReceive: "+intent.getAction());
	if(WIFI_AP_STATE_CHANGED_ACTION.equals(intent.getAction())) {
		    int cstate = intent.getIntExtra(EXTRA_WIFI_AP_STATE, -1);
		    if(cstate == WIFI_AP_STATE_ENABLED) {
		    	if(mHandler != null){
		    		mHandler.sendEmptyMessage(MESSAGE_AP_STATE_ENABLED);			    
		    	}
		    }if(cstate == WIFI_AP_STATE_DISABLED  || cstate == WIFI_AP_STATE_FAILED) {
			if(mHandler != null)
			    mHandler.sendEmptyMessage(MESSAGE_AP_STATE_FAILED);
		    }
		}
	 }
};

3 遺留問題

在配置wificonfiguration的時候有過屬性是hiddenSSID,這個是設置wifi熱點AP是否隱藏的,

但是設置wcfg.hiddenSSID = true或false並沒有發現有什麼不同,按理說設置爲true,ssid隱藏應該搜索不到這個熱點,

但是都可以搜索到。還請知道的可以留言指教,十分感謝。


之前有朋友說5.0系統的開啓熱點有問題,我這裏沒有5.0的手機,使用華爲p9Android6.0手機測試確實開啓不了熱點,需要添加write_settings,添加上此權限就可以成功開啓了。

DEMO下載


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章