好吧,我终于弄明白了,我希望我的答案能为将来遇到类似问题的人提供一些启示,因为这很糟糕,让我很头疼。
WiFiConfig
在中注册的
WiFiConfig文件
表via
WiFiConfigManager.addNetwork()
.
WifiConfigManager.addNetwork()
. 我假设如果那次行动成功了(即没有返回
-1
allowedAuthAlgorithms
allowedProtocols
,
allowedKeyManagers
和
allowedPairwiseCipher
BitSet
我创建的是不正确的,但是
addNetwork()
成功。我相信这是因为
添加网络()
除了验证配置
是有效的
WiFiConfig文件
桌子
,这与验证
给定WiFi接入点的配置是否正确
. 这是由源代码中的注释支持的
它们不像很多其他状态那样声明异步状态的传递
WiFiManager
.
WiFiConfig文件
对象与由我自己的代码生成的访问点的不一致性我注意到
WiFiConfig文件
为什么我
WiFiConfig文件
WiFiConfig文件
正确地说,他们似乎都在使用
BitWise
运算符来创建
Int
最终传递给
WiFiConfig.allowedProtocols.set()
WiFiConfig.allowedPairwiseCiphers.set()
WiFiConfig.allowedKeyManagement.set()
和
WiFiConfig.allowedAuthAlgorithm.set()
功能。
事实证明
位集合
中的元素的索引对应的WiFiConfig对象中的实例
String
曾经的数组
与上述相关
在WiFiConfig对象中。因此,如果您希望提供
protocols
,
keyManagements
,
pairwiseCiphers
或
authAlgorithms
set
,传入与所选协议匹配的字符串数组元素对应的正确索引。
在重新编写我的
创建代码后,问题自行解决。虽然我在原帖子中的代码中有一个错误也已被修复。
下面是新的WiFiConfig创建代码:
/**
* Emits a single of the [WifiConfiguration] created from the passed [scanResult] and [preSharedKey]
*/
private fun createWifiConfiguration(scanResult: WiFiScanResult, preSharedKey: String) = Single.fromCallable<WifiConfiguration> {
val auth = scanResult.auth
val keyManagement = scanResult.keyManagement
val pairwiseCipher = scanResult.pairwiseCipher
val config = WifiConfiguration()
config.SSID = "\"" + scanResult.ssid + "\""
config.BSSID = scanResult.bssid
if (auth.contains("WPA") || auth.contains("WPA2")) {
config.allowedProtocols.set(WifiConfiguration.Protocol.WPA)
config.allowedProtocols.set(WifiConfiguration.Protocol.RSN)
}
if (auth.contains("EAP"))
config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.LEAP)
else if (auth.contains("WPA") || auth.contains("WPA2"))
config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN)
else if (auth.contains("WEP"))
config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED)
if (keyManagement.contains("IEEE802.1X"))
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X)
else if (auth.contains("WPA") && keyManagement.contains("EAP"))
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP)
else if (auth.contains("WPA") && keyManagement.contains("PSK"))
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK)
else if (auth.contains("WPA2") && keyManagement.contains("PSK"))
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK)
if (pairwiseCipher.contains("CCMP") || pairwiseCipher.contains("TKIP")) {
config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP)
config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP)
}
if (preSharedKey.isNotEmpty()) {
if (auth.contains("WEP")) {
if (preSharedKey.matches("\\p{XDigit}+".toRegex())) {
config.wepKeys[0] = preSharedKey
} else {
config.wepKeys[0] = "\"" + preSharedKey + "\""
}
config.wepTxKeyIndex = 0
} else {
config.preSharedKey = "\"" + preSharedKey + "\""
}
}
config
}
下面是新的connect代码:
/**
* Connects to the wifi access point at specified [ssid] with specified [networkId]
* And returns the [WifiInfo] of the network that has been connected to
*/
private fun connect(context: Context,
wifiManager: WifiManager,
ssid: String,
networkId: Int) = Single.create<WifiInfo> { emitter ->
val wifiConnectionReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == WifiManager.NETWORK_STATE_CHANGED_ACTION) {
val networkInfo = intent.getParcelableExtra<NetworkInfo>(WifiManager.EXTRA_NETWORK_INFO) ?: return
if (networkInfo.detailedState == NetworkInfo.DetailedState.CONNECTED) {
val wifiInfo = intent.getParcelableExtra<WifiInfo>(WifiManager.EXTRA_WIFI_INFO) ?: return
if (ssid.unescape() == wifiInfo.ssid.unescape()) {
context.applicationContext.unregisterReceiver(this)
emitter.onSuccess(wifiInfo)
}
}
}
}
}
val networkStateChangedFilter = IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION)
networkStateChangedFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)
context.applicationContext.registerReceiver(wifiConnectionReceiver, networkStateChangedFilter)
emitter.setCancellable {
if (!emitter.isDisposed)
context.applicationContext.unregisterReceiver(wifiConnectionReceiver)
}
wifiManager.enableNetwork(networkId, true)
}