之前調查過Android中WIFI模塊的使用,也寫過兩篇學習總結的文章(http://smallwoniu.blog.51cto.com/3911954/1334951),後來發現DEMO裏面還是有許多不足之處,前段時間有不少人Q我,問到WIFI模塊中的一些細節,小弟這裏只能說聲抱歉,因爲當時的我也還沒研究到那個層次呀。。。,後來畢業設計選題乾脆直接選擇了關於WIFI熱點通信方面的題目,調查和整理了一些資料,進行了一段時間的學習算是彌補了自己的短板吧,主要還是希望自己能夠更加全面的掌握這方面的知識。
廢話不多說了!今天主要講解WIFI熱點通信的前期準備工作:
1.熱點創建:創建指定名稱的熱點。
2.熱點搜索:搜索附近可用熱點,生成列表。
3.熱點連接:在列表中點擊指定名稱的WIFI項,進行連接操作。
一.框架搭建
說明:
1.幾個權限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
2.相關類圖:
二.模塊講解
接下來通過以下三個部分功能來逐一剖析,在此之前首先看一張最終的效果圖加深以下印象:
(由於本章講解的部分是我的整個項目中的一部分,所以大家不用在意圖片素材等其他細節)
2.1熱點創建
點擊WIFI管理界面中創建熱點按鈕,首先會檢測當前WIFI是否可用,若可用則需將其關閉掉才能創建WIFI熱點,因爲手機熱點把手機的接收GPRS或3G信號轉化爲WIFI信號再發出去,即你的手機就成了一個WIFI熱點,所以共享和接收功能是不能同時進行的。之後就是創建指定名稱的熱點過程。熱點創建時序圖如下圖所示。
幾個核心方法:
startApWifiHot()
/** * create a hot wifi * * @param wifiName */ public boolean startApWifiHot(String wifiName) { Log.i(TAG, "into startApWifiHot(String wifiName) wifiName = " + wifiName); if (wifiManager.isWifiEnabled()) { wifiManager.setWifiEnabled(false); } if (mWifiHotAdmin != null) { return mWifiHotAdmin.startWifiAp(wifiName); } Log.i(TAG, "out startApWifiHot(String wifiName)"); return false; }
createWifiAp()
/** * start hot pot * @param wifiName * @return */ private boolean createWifiAp(String wifiName) { Log.i(TAG, "into startWifiAp() 啓動一個Wifi 熱點!"); Method method1 = null; boolean ret = false; try { //setWifiApEnabled is @hide, so reflect method1 = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class); WifiConfiguration apConfig = createPassHotWifiConfig(wifiName,Global.PASSWORD); ret = (Boolean) method1.invoke(mWifiManager, apConfig, true); } catch (IllegalArgumentException e) { e.printStackTrace(); Log.d(TAG, "stratWifiAp() IllegalArgumentException e"); } Log.i(TAG, "out startWifiAp() 啓動一個Wifi 熱點!"); return ret; }
2.2熱點搜索
點擊WIFI管理界面中搜索熱點按鈕,同創建一樣,首先需要檢測WIFI熱點是否關閉,將其關閉掉後才能打開WIFI搜索功能。在搜索完成後系統會發送WIFI狀態變化廣播來通知消息欄,這裏通過自定義廣播接收器接收了搜索成功消息,最後通過回調MainActivity中disPlayWifiScanResult()來顯示WIFI列表。
幾個核心方法:
scanWifiHot()
/** scan wifi hot **/ public void scanWifiHot() { Log.i(TAG, "into wifiHotScan()"); if(mWifiHotAdmin.isWifiApEnabled(wifiManager)) { mWifiHotAdmin.closeWifiAp(); } if (!wifiIsOpen()) { // WIFI is close currently //listen to the specified SSID wifi state registerWifiStateBroadcast(""); mWifiStateReceiver.setOperationsType(OperationsType.SCAN); //open wifi openWifi(); } else { // WIFI is open currently scanNearWifiHots(); } Log.i(TAG, "out wifiHotScan()"); }
scanNearWifiHots()
/** scan near wifi **/ private void scanNearWifiHots() { registerWifiScanBroadcast(); //start scan wifiManager.startScan(); }
說明:這裏的掃描實現過程是通過調用系統中WifiManager中掃描功能。
/** * 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 { mService.startScan(false); return true; } catch (RemoteException e) { return false; } }
2.3熱點連接
在搜索完成之後,需要在WIFI列表中找到遊戲的熱點,點擊連接過程會處理一系列邏輯:當前WIFI可用、是否已經連接、註冊WIFI狀態變化廣播等,之後,開啓獨立線程進行熱點匹配連接,熱點連接時序圖如圖所示。
幾個核心方法:
connectToHotpot()
/** * connect to hotpot * * @param ssid * @param wifiList * @param password */ public void connectToHotpot(String ssid, List<ScanResult> wifiList, String password) { if (ssid == null || password.equals("") || !ssid.equals(Global.HOTPOT_NAME)) { Log.d(TAG, "WIFI ssid is null or "); mWifiBroadCastOperator.disPlayWifiConnResult(false, null); return; } if (ssid.equalsIgnoreCase(mSSID) && isConnecting) { Log.d(TAG, "same ssid is connecting!"); mWifiBroadCastOperator.disPlayWifiConnResult(false, null); return; } if (!checkCoonectHotIsEnable(ssid, wifiList)) { Log.d(TAG, "ssid is not in the wifiList!"); mWifiBroadCastOperator.disPlayWifiConnResult(false, null); return; } if (!wifiIsOpen()) { //listen to ssid wifi registerWifiStateBroadcast(ssid); mWifiStateReceiver.setOperationsType(OperationsType.CONNECT); //open wifi openWifi(); } else { // real connecting enableNetwork(ssid, password); } }
enableNetwork()
/** * connect wifi hot really by thread * * @param ssid * @param password */ private void enableNetwork(final String ssid, final String password) { // delete more conneted wifi deleteMoreCon(ssid); registerWifiConnectBroadCast(); new Thread(new Runnable() { @Override public void run() { WifiConfiguration config = WifiHotConfigAdmin.createWifiNoPassInfo(ssid, password); // if connect is successful isConnecting = connectHotSpot(config); mSSID = ssid; if (!isConnecting) { Log.i(TAG, "into enableNetwork(WifiConfiguration wifiConfig) isConnecting =" + isConnecting); return; } } }).start(); }
connectHotSpot()
/** * connect wifi hot if successful * * @param wifiConfig * @return */ private boolean connectHotSpot(WifiConfiguration wifiConfig) { Log.i(TAG, "into enableNetwork(WifiConfiguration wifiConfig)"); //the ID of the newly created network description int wcgID = wifiManager.addNetwork(wifiConfig); Log.i(TAG, "into enableNetwork(WifiConfiguration wifiConfig) wcID = "+ wcgID); if (wcgID < 0) { return false; } boolean flag = wifiManager.enableNetwork(wcgID, true); Log.i(TAG, "out enableNetwork(WifiConfiguration wifiConfig)"); return flag; }
說明:連接熱點的過程實質上就是獲取熱點配置信息,之後將其添加到自己的網絡信息中同時使其可用。
至此,WIFI熱點通信的前期工作已經完成,連接的手機端已在同一局域網內,若再有手機連接進來會自動爲其分配該網段內的IP地址,接下來我們要做的就是在IP地址上實現數據的傳輸通信。在下一章中準備實現一個多人聊天室功能,希望能夠幫助到大家!
源碼下載:http://down.51cto.com/data/1812897