本文牵涉kotlinrxjava的相关知识

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//查询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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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 {
// 之前的写法是之前有连接的话先断连,后来发现小米华为这种一旦断连会特别积极的重连,导致指定的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 {
//初始化WifiConfiguration
val config = WifiConfiguration()
config.allowedAuthAlgorithms.clear()
config.allowedGroupCiphers.clear()
config.allowedKeyManagement.clear()
config.allowedPairwiseCiphers.clear()
config.allowedProtocols.clear()

//指定对应的SSID
config.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 = 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加密的场景,自己测试时,发现热点以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
}
}