本文牽涉kotlin
和rxjava
的相關知識
//查詢wifi信息需要申請權限,權限工具類就不要在意了,重點在下面
PermissionUtils.permission(PermissionConstants.LOCATION).callback(object : PermissionUtils.SimpleCallback {override fun onGranted() {//通過授權后,開啟一個等待框progressDialog.show()// 每2秒發送一次事件connectObs = Observable.interval(2, TimeUnit.SECONDS)// 取30次,還沒連上就結束,算這次超時.take(30).subscribeOn(Schedulers.computation()).subscribe({//開啟掃描WifiUtils.startScan()//連接WifiUtils.connect(padHotspotSsid, padHotspotPwd)}, {}, {if (progressDialog.isShowing) progressDialog.dismiss()ToastUtils.showShort("連接屏熱點超時")})}override fun onDenied() {ToastUtils.showShort("您拒絕了請求位置權限,我們無法搜尋網絡連接上屏,請在設置中打開")}}).request()
復制代碼
WifiUtils
object WifiUtils {val wifiManager: WifiManager = Utils.getApp().applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManagerval connectivityManager: ConnectivityManager = Utils.getApp().applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManagerfun startScan() {if (!wifiManager.isWifiEnabled) wifiManager.isWifiEnabled = true;wifiManager.startScan()}fun getScanResult() = wifiManager.scanResultsfun connect(ssid: String, pwd: String): Boolean {
// 之前的寫法是之前有連接的話先斷連,后來發現小米華為這種一旦斷連會特別積極的重連,導致指定的wifi搶不到
// 試過之后發現可以不用斷,就注釋掉了,直接走下面的代碼進行連接
// 如果已經連上wifi了
// if(NetworkUtils.isWifiConnected()) {直接忘掉
// if(!wifiManager.removeNetwork(wifiManager.connectionInfo.networkId)) {忘不掉,至少嘗試斷連
// wifiManager.disconnect()斷連在某些手機依然可能會失敗,或者返回true其實沒斷掉,或者斷掉了立馬又被重連。。等等
// }
// }//在掃描到的wifi中找ssid也就是wifi名相同的,如果沒有說明沒搜到,那么連不了,等下一次吧val scanResult = wifiManager.scanResults.singleOrNull { it.SSID == ssid }if (scanResult == null) {return false} else {//如果找到了wifi了,從配置表中搜索該wifi的配置config,也就是以前有沒有連接過var success = false//注意configuredNetworks中的ssid,系統源碼中加上了雙引號,這里比對的時候要去掉val config = wifiManager.configuredNetworks.singleOrNull { it.SSID.replace("\"", "") == ssid }if (config != null) {//如果找到了,那么直接連接,不要調用wifiManager.addNetwork 這個方法會更改config的!
// val netId = wifiManager.addNetwork(config)success = wifiManager. enableNetwork(config.networkId,true)} else {// 沒找到的話,就創建一個新的配置,然后正常的addNetWork、enableNetwork即可val padWifiNetwork = createWifiConfig(scanResult.SSID, pwd, getCipherType(scanResult.capabilities))val netId = wifiManager.addNetwork(padWifiNetwork)success = wifiManager. enableNetwork(netId,true)}LogUtils.d("連接${scanResult.SSID}...$success")return success}}fun isConnected(ssid: String): Boolean {return if (wifiManager.isWifiEnabled) {wifiManager.connectionInfo.ssid.replace("\"", "") == ssid} else {false}}private fun createWifiConfig(ssid: String, password: String, type: WifiCapability): WifiConfiguration {//初始化WifiConfigurationval config = WifiConfiguration()config.allowedAuthAlgorithms.clear()config.allowedGroupCiphers.clear()config.allowedKeyManagement.clear()config.allowedPairwiseCiphers.clear()config.allowedProtocols.clear()//指定對應的SSIDconfig.SSID = "\"" + ssid + "\""//如果之前有類似的配置val tempConfig = wifiManager.configuredNetworks.singleOrNull { it.SSID == "\"$ssid\"" }if (tempConfig != null) {//則清除舊有配置 不是自己創建的network 這里其實是刪不掉的wifiManager.removeNetwork(tempConfig.networkId)wifiManager.saveConfiguration()}//不需要密碼的場景if (type == WifiCapability.WIFI_CIPHER_NO_PASS) {config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE)//以WEP加密的場景} else if (type == WifiCapability.WIFI_CIPHER_WEP) {config.hiddenSSID = trueconfig.wepKeys[0] = "\"" + password + "\""config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN)config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED)config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE)config.wepTxKeyIndex = 0//以WPA加密的場景,自己測試時,發現熱點以WPA2建立時,同樣可以用這種配置連接} else if (type == WifiCapability.WIFI_CIPHER_WPA) {config.preSharedKey = "\"" + password + "\""config.hiddenSSID = trueconfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN)config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP)config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK)config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP)config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP)config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP)config.status = WifiConfiguration.Status.ENABLED}return config}fun getCipherType(capabilities: String): WifiCapability {return if (capabilities.contains("WEB")) {WifiCapability.WIFI_CIPHER_WEP} else if (capabilities.contains("PSK")) {WifiCapability.WIFI_CIPHER_WPA} else if (capabilities.contains("WPS")) {WifiCapability.WIFI_CIPHER_NO_PASS} else {WifiCapability.WIFI_CIPHER_NO_PASS}}fun getDhcpInfo(): String {val dhcpInfo = wifiManager.dhcpInforeturn intIP2StringIP(dhcpInfo.serverAddress)}fun intIP2StringIP(ip: Int): String {return (ip and 0xFF).toString() + "." +(ip shr 8 and 0xFF) + "." +(ip shr 16 and 0xFF) + "." +(ip shr 24 and 0xFF)}
}enum class WifiCapability {WIFI_CIPHER_WEP, WIFI_CIPHER_WPA, WIFI_CIPHER_NO_PASS
}
}
復制代碼