WIFI的相關操作

首先要獲取 WifiManager,後面的所有操作基本上都要用到。

val wifiManager = getSystemService(Context.WIFI_SERVICE) as WifiManager

打開關閉WIFI

打開或者關閉WIFI直接調用 WifiManager.isWifiEnabled = true / false 就可以了,但是要監聽操作結果的話,有兩種方法,一個是監聽廣播,一個是寫循環主動查詢,我個人覺得還是主動查詢可靠點,下面是我封裝的方法:

/**
 * 異步打開、關閉wifi,並回調。10秒超時。
 * @param enabled 打開/關閉 WIFI。
 * @param callback 結果回調,success:打開/關閉成功。UI線程回調。
 */
private fun WifiManager.enable(enabled: Boolean, callback: (success: Boolean) -> Unit) {
    GlobalScope.launch(Dispatchers.IO) {
        // 當前狀態一致,直接回調
        if (isWifiEnabled == enabled) {
            GlobalScope.launch(Dispatchers.Main) { callback.invoke(true) }
            return@launch
        }

        isWifiEnabled = enabled

        repeat(10) {
            delay(1000)
            // 當前狀態一致,直接回調
            if (isWifiEnabled == enabled) {
                GlobalScope.launch(Dispatchers.Main) { callback.invoke(true) }
                return@launch
            }
        }

        GlobalScope.launch(Dispatchers.Main) { callback.invoke(false) }
    }
}

// 這樣調用即可
wifiManager.enable(isChecked) { success ->
    // 直接用 wifiManager.isWifiEnabled 判斷更可靠點
    if (wifiManager.isWifiEnabled) {
        // WIFI 已打開
    } else {
        // WIFI 已關閉
    }
}

掃描WIFI

掃描結果通過 wifiManager.scanResults 獲取,但是獲取到的可能是以前的掃描結果,所以我們要等收到廣播後再獲取結果。

// 廣播接收器
private val receiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        if (intent?.action == WifiManager.SCAN_RESULTS_AVAILABLE_ACTION) {
            wifiManager.scanResults.filter {
                !TextUtils.isEmpty(it.SSID)
            }.forEach {scanResult->
                LogUtils.d(TAG, scanResult)
                // 展示列表
            }
        }
    }
}

// 註冊廣播
registerReceiver(receiver, IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION))
// 掃描
wifiManager.startScan()
// 註銷廣播
unregisterReceiver(receiver)

連接WIFI

連接WIFI要調用好幾個接口,首先要根據帳號密碼生成WifiConfiguration,然後addNetwork(config),返回-1表示失敗,addNetwork只是把配置添加到配置列表,還需要調用 enableNetwork(networkId, true)纔是真正的連接WIFI,最後調用saveConfiguration保存一下。操作結果依然是通過廣播接收。

1、生成WifiConfiguration比較複雜,這裏寫了個獨立的方法,代碼是網上的稍作修改了。

// 獲取已經存在的SSID對應的配置
private fun WifiManager.getConfiguredNetwork(ssid: String): WifiConfiguration? {
    configuredNetworks.forEach {
        if (it.SSID == "\"$ssid\"") return it
    }
    return null
}

private fun WifiManager.createWifiConfiguration(ssid: String, password: String, scanResult: ScanResult? = null): WifiConfiguration {
    // 判斷是否已經存在
    val config = getConfiguredNetwork(ssid)
    if (config != null) {
        LogUtils.d(TAG, "已經存在 $ssid 執行移除操作")
        val successful = removeNetwork(config.networkId)
        LogUtils.d(TAG, "移除操作 ${if (successful) "成功" else "失敗"}")
    }

    val capabilities = scanResult?.capabilities ?: "wpa"
    return WifiConfiguration().apply {
        allowedAuthAlgorithms.clear()
        allowedGroupCiphers.clear()
        allowedKeyManagement.clear()
        allowedPairwiseCiphers.clear()
        allowedProtocols.clear()
        SSID = "\"" + ssid + "\""

        when {
            capabilities.contains("wep", ignoreCase = true) -> {
                hiddenSSID = true
                wepKeys[0] = "\"" + password + "\""
                allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED)
                allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP)
                allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP)
                allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40)
                allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104)
                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE)
                wepTxKeyIndex = 0
            }
            capabilities.contains("psk", ignoreCase = true) -> {
                preSharedKey = "\"" + password + "\""
                hiddenSSID = true
                allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN)
                allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP)
                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK)
                allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP)
                allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP)
                allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP)
                status = WifiConfiguration.Status.ENABLED
            }
            else -> {
                // 沒有密碼
                allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE)
            }
        }
    }
}

2、連接

// 這裏增加個變量多重判斷一下
private var enableNetworkSuccessful = false

private fun connect() {
    val ssid = et_name.text.toString()
    val password = et_password.text.toString()

    val config = wifiManager.createWifiConfiguration(ssid, password, wifiWrapper?.wifi)
    LogUtils.d(TAG, "創建 WifiConfiguration:$config")
    val networkId = wifiManager.addNetwork(config)
    LogUtils.d(TAG, "addNetwork 返回:$networkId")
    enableNetworkSuccessful = wifiManager.enableNetwork(networkId, true)
    LogUtils.d(TAG, "enableNetwork 返回:$enableNetworkSuccessful")
    if (enableNetworkSuccessful) {
        val successful = wifiManager.saveConfiguration()
        LogUtils.d(TAG, "saveConfiguration 返回:$successful")
    }
}

3、監聽結果

private val receiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        when (intent?.action) {
            WifiManager.SUPPLICANT_STATE_CHANGED_ACTION -> {
                LogUtils.i(TAG, "收到廣播:SUPPLICANT_STATE_CHANGED_ACTION")
                val error = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, 123)
                if (WifiManager.ERROR_AUTHENTICATING == error) {
                    LogUtils.e(TAG, "密碼錯誤")
                    ToastUtils.show("密碼錯誤")
                    progressDialog.dismiss()
                }
            }
            WifiManager.NETWORK_STATE_CHANGED_ACTION -> {
                LogUtils.i(TAG, "收到廣播:NETWORK_STATE_CHANGED_ACTION")
                try {
                    val info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO) as? NetworkInfo
                    LogUtils.i(TAG, "EXTRA_NETWORK_INFO=$info")
                    when (info?.state) {
                        NetworkInfo.State.CONNECTING -> ToastUtils.show("正在連接...")
                        NetworkInfo.State.CONNECTED -> {
                            // 連接成功
                            if (enableNetworkSuccessful) {
                                LogUtils.i(TAG, "CONNECTED")
                                ToastUtils.show("連接成功")
                                successful = true
                                progressDialog.dismiss()
                                dismiss()
                            }
                        }
                        else -> Unit
                    }
                } catch (e: Exception) {
                    LogUtils.printStackTrace(e)
                }
            }
        }
    }
}

// 註冊廣播
registerReceiver(receiver, IntentFilter().apply {
    addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)
    addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION)
})
// 註銷廣播
unregisterReceiver(receiver)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章