前言:
作為一名系統(tǒng)開發(fā)者, 對應(yīng)用上 WiFi 的研發(fā)是一個 "門外漢" 的角色, 通過閱讀 Android 源碼, 逐漸對這一部分有了些許認(rèn)識. 下方主要圍繞 WifiManager 的函數(shù)系, 做了一些類似工具類的封裝, 語言盡量簡單, 希望對各位系統(tǒng)開發(fā)者能起到幫助的作用, 具體內(nèi)容以 解釋 + 注釋 + 代碼塊的形式展示給大伙.
簡介: 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的簡單介紹;
一些簡單的工具類的封裝 以及 簡要說明:
- 獲取 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é):
如上, 針對會使用到的函數(shù)做個簡單的封裝, 使大家用起來更加簡單明了, 希望能帶給你一些方便.
如有疑問, 請簡信, 或郵箱告知. 亦可下方評論區(qū)留言.
qq 郵箱: 1281641968@qq.com