android連接指定wifi

本文牽涉kotlinrxjava的相關(guān)知識

//查詢wifi信息需要申請權(quán)限,權(quán)限工具類就不要在意了,重點在下面
PermissionUtils.permission(PermissionConstants.LOCATION).callback(object : PermissionUtils.SimpleCallback {
                    override fun onGranted() {
                    //通過授權(quán)后,開啟一個等待框
                        progressDialog.show()
                    //    每2秒發(fā)送一次事件
                        connectObs = Observable.interval(2, TimeUnit.SECONDS)
                    //    取30次,還沒連上就結(jié)束,算這次超時
                                .take(30)
                                .subscribeOn(Schedulers.computation())
                                .subscribe({
                                    //開啟掃描
                                    WifiUtils.startScan()
                                    //連接
                                    WifiUtils.connect(padHotspotSsid, padHotspotPwd)
                                }, {}, {
                                    if (progressDialog.isShowing) progressDialog.dismiss()
                                    ToastUtils.showShort("連接屏熱點超時")
                                })
                    }

                    override fun onDenied() {
                        ToastUtils.showShort("您拒絕了請求位置權(quán)限,我們無法搜尋網(wǎng)絡(luò)連接上屏,請在設(shè)置中打開")
                    }
                }).request()

WifiUtils

object WifiUtils {
    val wifiManager: WifiManager = Utils.getApp().applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
    val connectivityManager: ConnectivityManager = Utils.getApp().applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    fun startScan() {
        if (!wifiManager.isWifiEnabled) wifiManager.isWifiEnabled = true;
        wifiManager.startScan()
    }

    fun getScanResult() = wifiManager.scanResults

    fun connect(ssid: String, pwd: String): Boolean {
//      之前的寫法是之前有連接的話先斷連,后來發(fā)現(xiàn)小米華為這種一旦斷連會特別積極的重連,導(dǎo)致指定的wifi搶不到
//      試過之后發(fā)現(xiàn)可以不用斷,就注釋掉了,直接走下面的代碼進行連接
//        如果已經(jīng)連上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,系統(tǒng)源碼中加上了雙引號,這里比對的時候要去掉
            val config = wifiManager.configuredNetworks.singleOrNull { it.SSID.replace("\"", "") == ssid }
            if (config != null) {
                //如果找到了,那么直接連接,不要調(diào)用wifiManager.addNetwork  這個方法會更改config的!
//                val netId = wifiManager.addNetwork(config)
                success = wifiManager. enableNetwork(config.networkId,true)
            } else {
                // 沒找到的話,就創(chuàng)建一個新的配置,然后正常的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 {
        //初始化WifiConfiguration
        val config = WifiConfiguration()
        config.allowedAuthAlgorithms.clear()
        config.allowedGroupCiphers.clear()
        config.allowedKeyManagement.clear()
        config.allowedPairwiseCiphers.clear()
        config.allowedProtocols.clear()

        //指定對應(yīng)的SSID
        config.SSID = "\"" + ssid + "\""

        //如果之前有類似的配置
        val tempConfig = wifiManager.configuredNetworks.singleOrNull { it.SSID == "\"$ssid\"" }
        if (tempConfig != null) {
            //則清除舊有配置  不是自己創(chuàng)建的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 = true
            config.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加密的場景,自己測試時,發(fā)現(xiàn)熱點以WPA2建立時,同樣可以用這種配置連接
        } else if (type == WifiCapability.WIFI_CIPHER_WPA) {
            config.preSharedKey = "\"" + password + "\""
            config.hiddenSSID = true
            config.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.dhcpInfo
        return 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
}
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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