Android-WiFi開發(fā)之 WifiManager

前言:

作為一名系統(tǒng)開發(fā)者, 對應(yīng)用上 WiFi 的研發(fā)是一個 "門外漢" 的角色, 通過閱讀 Android 源碼, 逐漸對這一部分有了些許認(rèn)識. 下方主要圍繞 WifiManager 的函數(shù)系, 做了一些類似工具類的封裝, 語言盡量簡單, 希望對各位系統(tǒng)開發(fā)者能起到幫助的作用, 具體內(nèi)容以 解釋 + 注釋 + 代碼塊的形式展示給大伙.

  1. 簡介: WifiManager這個類, 是 Android 暴露給開發(fā)者使用的一個系統(tǒng)服務(wù)管理類, 其中包含對WiFi的響應(yīng)的操作函數(shù); 其隱藏掉的系統(tǒng)服務(wù)類為IWifiService, 為Android私有的, 其具體實(shí)現(xiàn), 未暴露給用戶; 只需要使用WifiManager進(jìn)行函數(shù)操作完成UI, 監(jiān)聽對應(yīng)的廣播消息, 就可完成功能了. 換言之, WifiManager會調(diào)用service簡介地和framework層, 驅(qū)動層進(jìn)行函數(shù)調(diào)用, 然后驅(qū)動層會回調(diào)至上層, 以廣播的形式實(shí)現(xiàn)通知; 這是目前WiFi的簡單介紹;

  2. 一些簡單的工具類的封裝 以及 簡要說明:

  • 獲取 WifiManager 實(shí)例:
// 獲取 WifiManager 實(shí)例. 
public static WifiManager getWifiManager(Context context) {
    return context == null ? null : (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
}

注意: 這是官方推薦的獲取 WifiManager 類的方式; 其實(shí)在看源碼的時候, 會有一個公共的構(gòu)造函數(shù), 但是是需要IWifiService的, 這個類是google私有的, 屬于系統(tǒng)安全級別的API類, 所以, 調(diào)用上面的方法, 谷歌會幫你實(shí)例化IWifiService, 并且后續(xù)的連接, 忘記, 保存的真實(shí)實(shí)現(xiàn)都是由service來完成的;

  • 開啟, 關(guān)閉 WiFi: (操作這個函數(shù)的時候, 就會觸發(fā)系統(tǒng)回調(diào)WiFi狀態(tài)發(fā)生改變的廣播)
// 開啟/關(guān)閉 WIFI.
public static boolean setWifiEnabled(WifiManager manager, boolean enabled) {
    return manager != null && manager.setWifiEnabled(enabled);
}
  • 獲取 WiFi 硬件的狀態(tài):
// 獲取 WIFI 的狀態(tài).
public static int getWifiState(WifiManager manager) {
    return manager == null ? WifiManager.WIFI_STATE_UNKNOWN : manager.getWifiState();
}

/**
 * 注意:
 * WiFi 的狀態(tài)目前有五種, 分別是:
 * WifiManager.WIFI_STATE_ENABLING: WiFi正要開啟的狀態(tài), 是 Enabled 和 Disabled 的臨界狀態(tài);
 *  WifiManager.WIFI_STATE_ENABLED: WiFi已經(jīng)完全開啟的狀態(tài);
 *  WifiManager.WIFI_STATE_DISABLING: WiFi正要關(guān)閉的狀態(tài), 是 Disabled 和 Enabled 的臨界狀態(tài);
 *  WifiManager.WIFI_STATE_DISABLED: WiFi已經(jīng)完全關(guān)閉的狀態(tài);
 *  WifiManager.WIFI_STATE_UNKNOWN: WiFi未知的狀態(tài), WiFi開啟, 關(guān)閉過程中出現(xiàn)異常, 或是廠家未配備WiFi外掛模塊會出現(xiàn)的情況;
*/
  • 開始掃描 WiFi 熱點(diǎn), 在確認(rèn)開啟 WiFi 之后, 我們就可以調(diào)用 startScan() 函數(shù)開始掃描附近的熱點(diǎn)了, 即:
// 開始掃描 WIFI. 
public static void startScanWifi(WifiManager manager) {
    if (manager != null) {
        manager.startScan();
    }
}
  • 獲取掃描到的 WiFi 熱點(diǎn)的結(jié)果:
// 獲取掃描 WIFI 的熱點(diǎn): 
public static List<ScanResult> getScanResult(WifiManager manager) {
    return manager == null ? null : manager.getScanResult();
}
  • 獲取配置好的 WiFi 信息:
// 獲取已經(jīng)保存過的/配置好的 WIFI 熱點(diǎn). 
public static List<WifiConfiguration> getConfiguredNetworks(WifiManager manager) {
    return manager == null ? null : manager.WifiConfiguration();
}

/** 
 * 注意: 
 * Android 的 WiFi 連接, 大概可以分為如下兩種情況:
 * a. 無密碼的, 可直接連接, 連接過程中, 此熱點(diǎn)一直有, 不管最后是否需要其他方式進(jìn)行驗證操作, 但凡連接成功, 即  
 * 刻進(jìn)行了對此熱點(diǎn)的配置進(jìn)行保存;
 * b. 有密碼的, 暫且不論何種加密手段, 只要用戶輸入密碼, 點(diǎn)擊連接, 如果連接途中, 此熱點(diǎn)一直有, 不論連接成功還
 * 是失敗, 都即刻對此熱點(diǎn)的配置進(jìn)行了保存操作;  使用上述的方式獲取到的WiFi的配置, 就是上面進(jìn)行操作保存的WiFi配
 * 置;
 * c. 連接多個WiFi成功之后, 然后關(guān)閉WiFi, 下次開啟WiFi的時候, 驅(qū)動會主動幫你連接這其中配置好的其中一個WiFi;
 * /
  • 獲取對應(yīng)到 ScanResult 的 WifiConfiguration, 通常, 此配置對應(yīng)一個 BSSID, 可能是 null;
    List<WifiConfiguration> configs = wifiManager.getMatchingWifiConfig(scanResult);

    // 可以打印一下看具體的情況:
    if (configs == null || configs.isEmpty()) return;
    for (WifiConfiguration config : configs) {
        Log.v(TAG, "config = " + config);
    }
  • 連接WiFi: 連接 WIFI, 安卓提供了兩種方式, 一種是通過配置連接, 另一種是通過 networkId 來連接, 兩種方式各有使用場景, 可根據(jù)需要選擇使用, 封裝后的函數(shù)如下: (反射可抽取方法, 單獨(dú)提煉, 此處不展示.)
// 使用 WifiConfiguration 連接. 
public static void connectByConfig(WifiManager manager, WifiConfiguration config) {
    if (manager == null) {
        return;
    }
    try {
        Method connect = manager.getClass().getDeclaredMethod("connect", WifiConfiguration.class, Class.forName("android.net.wifi.WifiManager$ActionListener"));
        if (connect != null) {
            connect.setAccessible(true);
            connect.invoke(manager, config, null);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
    
// 使用 networkId 連接. 
public static void connectByNetworkId(WifiManager manager, int networkId) {
    if (manager == null) {
        return;
    }
    try {
        Method connect = manager.getClass().getDeclaredMethod("connect", int.class, Class.forName("android.net.wifi.WifiManager$ActionListener"));
        if (connect != null) {
            connect.setAccessible(true);
            connect.invoke(manager, networkId, null);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • 保存網(wǎng)絡(luò):
// 保存網(wǎng)絡(luò). 
public static void saveNetworkByConfig(WifiManager manager, WifiConfiguration config) {
    if (manager == null) {
        return;
    }
    try {
        Method save = manager.getClass().getDeclaredMethod("save", WifiConfiguration.class, Class.forName("android.net.wifi.WifiManager$ActionListener"));
        if (save != null) {
            save.setAccessible(true);
            save.invoke(manager, config, null);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • 添加網(wǎng)絡(luò):
// 添加網(wǎng)絡(luò). 
public static int addNetwork(WifiManager manager, WifiConfiguration config) {
    if (manager != null) {
        manager.addNetwork(config);
    }
}
  • 忘記網(wǎng)絡(luò):
// 忘記網(wǎng)絡(luò).
public static void forgetNetwork(WifiManager manager, int networkId) {
    if (manager == null) {
        return;
    }
    try {
        Method forget = manager.getClass().getDeclaredMethod("forget", int.class, Class.forName("android.net.wifi.WifiManager$ActionListener"));
        if (forget != null) {
            forget.setAccessible(true);
            forget.invoke(manager, networkId, null);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • 禁用網(wǎng)絡(luò):
// 禁用網(wǎng)絡(luò). 
public static void disableNetwork(WifiManager manager, int netId) {
    if (manager == null) {
        return;
    }
    try {
        Method disable = manager.getClass().getDeclaredMethod("disable", int.class, Class.forName("android.net.wifi.WifiManager$ActionListener"));
        if (disable != null) {
            disable.setAccessible(true);
            disable.invoke(manager, networkId, null);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • 斷開連接:
// 斷開連接. 
public static boolean disconnectNetwork(WifiManager manager) {
    return manager != null && manager.disconnect();
}
  • 短暫禁用網(wǎng)絡(luò):
// 禁用短暫網(wǎng)絡(luò).
public static void disableEphemeralNetwork(WifiManager manager, String SSID) {
    if (manager == null || TextUtils.isEmpty(SSID)) 
        return;
        try {
        Method disableEphemeralNetwork = manager.getClass().getDeclaredMethod("disableEphemeralNetwork", String.class);
        if (disableEphemeralNetwork != null) {
            disableEphemeralNetwork.setAccessible(true);
            disableEphemeralNetwork.invoke(manager, SSID);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

小結(jié):

  1. 如上, 針對會使用到的函數(shù)做個簡單的封裝, 使大家用起來更加簡單明了, 希望能帶給你一些方便.

  2. 如有疑問, 請簡信, 或郵箱告知. 亦可下方評論區(qū)留言.

  3. qq 郵箱: 1281641968@qq.com

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末尿赚,一起剝皮案震驚了整個濱河市刃跛,隨后出現(xiàn)的幾起案子蜓肆,更是在濱河造成了極大的恐慌,老刑警劉巖纠亚,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)谈竿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來摸吠,“玉大人,你說我怎么就攤上這事嚎花〈缌。” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵紊选,是天一觀的道長啼止。 經(jīng)常有香客問我道逗,道長,這世上最難降的妖魔是什么献烦? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任滓窍,我火速辦了婚禮,結(jié)果婚禮上巩那,老公的妹妹穿的比我還像新娘吏夯。我一直安慰自己,他們只是感情好即横,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布噪生。 她就那樣靜靜地躺著,像睡著了一般东囚。 火紅的嫁衣襯著肌膚如雪跺嗽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天页藻,我揣著相機(jī)與錄音桨嫁,去河邊找鬼。 笑死份帐,一個胖子當(dāng)著我的面吹牛璃吧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播弥鹦,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼肚逸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了彬坏?” 一聲冷哼從身側(cè)響起朦促,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎栓始,沒想到半個月后务冕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡幻赚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年禀忆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片落恼。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡箩退,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出佳谦,到底是詐尸還是另有隱情戴涝,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站啥刻,受9級特大地震影響奸鸯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜可帽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一娄涩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧映跟,春花似錦蓄拣、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至剃法,卻和暖如春碎捺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背贷洲。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工收厨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人优构。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓诵叁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親钦椭。 傳聞我的和親對象是個殘疾皇子拧额,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容