1. 程式人生 > >Android 設定Wifi熱點、開啟與關閉的監聽

Android 設定Wifi熱點、開啟與關閉的監聽

用過360的面對面快傳,快牙的朋友應該都知道,它們在兩臺裝置間實現檔案傳輸都是通過WiFi熱點實現的,下面我們就來探討一下如何設定熱點名和密碼,並自動建立一個wifi熱點吧,以及如何監聽熱點的開啟與關閉。

一、建立WiFi熱點

其實建立熱點很簡單,先獲取到wifi的服務,再配置熱點名稱、密碼等等,然後再通過反射開啟它就OK了,需要注意的是手機的WiFi連線與熱點是不可同時開啟的,也就是說如果手機連上了一個現有WiFi,就無法開啟自身熱點,反之亦然。所以在開啟熱點是先判斷WiFi是否開啟,如果開啟則先關閉WiFi,然後再根據設定的熱點名和密碼建立熱點。廢話少說,直接上程式碼:

package com.wjj.wifihotmanager;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
  
/**
 * @ClassName:  WifiHotUtil   
 * @Description:  列印日誌資訊WiFi熱點工具
 * @author: jajuan.wang  
 * @date:   2015-05-28 15:12  
 * version:1.0.0
 */   
public class WifiHotUtil {  
    public static final String TAG = "WifiApAdmin";  
      
    private WifiManager mWifiManager = null;  
    
    private Context mContext = null;  
    public WifiHotUtil(Context context) {  
        mContext = context;  
        mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
    }  
    
    public void startWifiAp(String ssid, String passwd) 
    {  
        //wifi和熱點不能同時開啟,所以開啟熱點的時候需要關閉wifi
        if (mWifiManager.isWifiEnabled()) {  
            mWifiManager.setWifiEnabled(false);  
        }   

        if (!isWifiApEnabled()) {
            stratWifiAp(ssid, passwd); 
        } 
    }  
  
    /**
     * 設定熱點名稱及密碼,並建立熱點
     * @param mSSID
     * @param mPasswd
     */
    private void stratWifiAp(String mSSID, String mPasswd) {  
        Method method1 = null;  
        try {  
        	//通過反射機制開啟熱點
            method1 = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);  
            WifiConfiguration netConfig = new WifiConfiguration();  
  
            netConfig.SSID = mSSID;  
            netConfig.preSharedKey = mPasswd;  
  
            netConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);  
            netConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);  
            netConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);  
            netConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);  
            netConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);  
            netConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);  
            netConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);  
            netConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);  
            method1.invoke(mWifiManager, netConfig, true);  
  
        } catch (IllegalArgumentException e) {  
            e.printStackTrace();  
        } catch (IllegalAccessException e) {  
            e.printStackTrace();  
        } catch (InvocationTargetException e) {  
            e.printStackTrace();  
        } catch (SecurityException e) {  
            e.printStackTrace();  
        } catch (NoSuchMethodException e) {  
            e.printStackTrace();  
        }
    }  
  
  
    /**
     * 熱點開關是否開啟
     * @return
     */
    public boolean isWifiApEnabled() {  
        try {  
            Method method = mWifiManager.getClass().getMethod("isWifiApEnabled");  
            method.setAccessible(true);  
            return (Boolean) method.invoke(mWifiManager);  
        } catch (NoSuchMethodException e) {  
            e.printStackTrace();  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return false;  
    }  
    
    /**
     * 關閉WiFi熱點
     */
    public void closeWifiAp() {  
        WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);   
        if (isWifiApEnabled()) {  
            try {  
                Method method = wifiManager.getClass().getMethod("getWifiApConfiguration");  
                method.setAccessible(true);  
                WifiConfiguration config = (WifiConfiguration) method.invoke(wifiManager);  
                Method method2 = wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);  
                method2.invoke(wifiManager, config, false);  
            } catch (NoSuchMethodException e) {  
                e.printStackTrace();  
            } catch (IllegalArgumentException e) {  
                e.printStackTrace();  
            } catch (IllegalAccessException e) {  
                e.printStackTrace();  
            } catch (InvocationTargetException e) {  
                e.printStackTrace();  
            }  
        } 
    }
  
} 


呼叫方式:在activity中:

//例項化WiFi熱點工具類
wifiHotUtil = new WifiHotUtil(this);
//建立熱點
wifiHotUtil.startWifiAp(defaultHotName, defaultHotPwd);
//關閉熱點
wifiHotUtil.closeWifiAp();

二、監聽熱點的開啟與關閉

經過查詢資料發現,android的行動式熱點開啟與關閉都會發出 android.net.wifi.WIFI_AP_STATE_CHANGED 的廣播,但是行動式熱點相關的資訊在WiFimanage中是隱藏的,這個廣播是隱藏的。那我們怎麼監聽呢?好不容易在stackoverflow上找到了解決辦法,連線地址:

Monitoring the Hotspot state in Android,實現程式碼如下:

private BroadcastReceiver wifiReceiver = new BroadcastReceiver(){
        public void onReceive(Context context, Intent intent) {
        	String action = intent.getAction();
            if ("android.net.wifi.WIFI_AP_STATE_CHANGED".equals(action)) {
            	//行動式熱點的狀態為:10---正在關閉;11---已關閉;12---正在開啟;13---已開啟
                int state = intent.getIntExtra("wifi_state",  0);
                Log.i(TAG, "state= "+state);
                wiFiAPObserver.stateChanged(state);
            }
        }
};
註冊這個廣播監聽器,就可以監聽熱點的開啟與關閉狀態了。

我使用的是服務+觀察者模式,應用啟動時啟動熱點監聽服務,用於監聽熱點開啟與關閉的狀態。activity或其他需要獲取熱點狀態的地方可以通過服務註冊監聽器,當熱點狀態改變時會遍歷通知每個註冊的例項。上程式碼:
package com.wjj.wifihotmanager;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;

/**
 * @ClassName:  WiFiAPService   
 * @Description:  wifi hot manage service
 * @author: jajuan.wang  
 * @date:   2015-06-09 00:43  
 * version:1.0.0
 */
public class WiFiAPService extends Service {
	
	private static String TAG = "WiFiAPService";
	
	public static String ACTION_START_SERVICE = "action_start_service";
	public static String ACTION_STOP_SERVICE = "action_stop_service";
	private static WiFiAPObserver wiFiAPObserver = new WiFiAPObserver();
	
	
	/**
	 * static method to start service
	 * @param context
	 */
	public static void startService(Context context) {
		Intent intent = new Intent(context, WiFiAPService.class);
		intent.setAction(ACTION_START_SERVICE);
		context.startService(intent);
	}
	
	/**
	 * static method to stop service
	 * @param context
	 */
	public static void stopService(Context context) {
		Intent intent = new Intent(context, WiFiAPService.class);
		intent.setAction(ACTION_STOP_SERVICE);
		context.startService(intent);
	}
	
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		super.onStartCommand(intent, flags, startId);
		Log.i(TAG, "intent.getAction()="+intent.getAction());
		// option based on action
		if (intent.getAction().equals(ACTION_START_SERVICE) == true) {
			//startService();
		} else if (intent.getAction().equals(ACTION_STOP_SERVICE) == true) {
			stopSelf();
		} 
		//重傳Intent。使用這個返回值時,如果在執行完onStartCommand後,服務被異常kill掉,系統會自動重啟該服務,並將Intent的值傳入。
		return Service.START_REDELIVER_INTENT;
	}
	
	@Override
	public void onCreate() {
		registerReceiver(wifiReceiver,new IntentFilter("android.net.wifi.WIFI_AP_STATE_CHANGED"));
		super.onCreate();
	}
	
	
	
	@Override
	public void onDestroy() {
		unregisterReceiver(wifiReceiver);
		wiFiAPObserver.clearWiFiAPListener();
		super.onDestroy();
	}
	
	/**
	 * register wiFiAPListener
	 * @param wiFiAPListener
	 */
	public static void addWiFiAPListener(WiFiAPListener wiFiAPListener) {
		wiFiAPObserver.addWiFiAPListener(wiFiAPListener);
	}
	
	/**
	 * remove wiFiAPListener
	 * @param wiFiAPListener
	 */
	public static void removeWiFiAPListener(WiFiAPListener wiFiAPListener) {
		wiFiAPObserver.removeWiFiAPListener(wiFiAPListener);
	}


	private BroadcastReceiver wifiReceiver = new BroadcastReceiver(){
        public void onReceive(Context context, Intent intent) {
        	String action = intent.getAction();
            if ("android.net.wifi.WIFI_AP_STATE_CHANGED".equals(action)) {
            	//行動式熱點的狀態為:10---正在關閉;11---已關閉;12---正在開啟;13---已開啟
                int state = intent.getIntExtra("wifi_state",  0);
                Log.i(TAG, "state= "+state);
                wiFiAPObserver.stateChanged(state);
            }
        }
	};

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}

}

熱點監聽器:

package com.wjj.wifihotmanager;

/**
 * @ClassName:  WiFiAPListener   
 * @Description:  Listenning the state of wifi hot
 * @author: jajuan.wang  
 * @date:   2015-06-09 00:52  
 * version:1.0.0
 */
public interface WiFiAPListener {
	
    public static final int WIFI_AP_CLOSEING 		= 10;  //wifi hot is closeing
    public static final int WIFI_AP_CLOSE_SUCCESS 	= 11;  //wifi hot close success
    public static final int WIFI_AP_OPENING 		= 12;  //WiFi hot is opening 
    public static final int WIFI_AP_OPEN_SUCCESS 	= 13;  //WiFi hot open success

	/**
	 * the state of wifi hot changed
	 * @param state
	 */
	public void stateChanged(int state) ;
}
熱點狀態觀察者:
package com.wjj.wifihotmanager;

import java.util.HashSet;

/**
 * @ClassName:  WiFiAPObserver   
 * @Description:  Listenning the state of wifi hot
 * @author: jajuan.wang  
 * @date:   2015-06-09 00:58  
 * version:1.0.0
 */
public class WiFiAPObserver implements WiFiAPListener {
	
	/**
	 * the set to save all registed listener
	 */
	private HashSet<WiFiAPListener> listenerSet = new HashSet<WiFiAPListener>();
	
	/**
	 * add wiFiAPListener
	 * @param wiFiAPListener
	 */
	public void addWiFiAPListener(WiFiAPListener wiFiAPListener) {
		if (!listenerSet.contains(wiFiAPListener)) {
			listenerSet.add(wiFiAPListener);
		}
	}
	
	/**
	 * remove the wiFiAPListener
	 * @param wiFiAPListener
	 */
	public void removeWiFiAPListener(WiFiAPListener wiFiAPListener) {
		if (listenerSet.contains(wiFiAPListener)) {
			listenerSet.remove(wiFiAPListener);
		}
	}
	
	/**
	 * remove all WiFiAPListener
	 */
	public void clearWiFiAPListener() {
		listenerSet.clear();
	}

	@Override
	public void stateChanged(int state) {
		//notify all Listener the state changed 
		for (WiFiAPListener wiFiAPListener : listenerSet) {
			wiFiAPListener.stateChanged(state);
		}
	}

}

原始碼下載