公司有个自动连接目标wifi的需求,查阅了很多资料,记录一下自己测试有用的方式。
扫描和获取wifi列表可以查看:
https://blog.csdn.net/CSDNzzh95/article/details/131635916
获得wifiInfo: ScanResult数据
android 10以下的版本
/**
* wifi设置
* @param ssid
* @param pws
* @param isHasPws
*/
private fun getWifiConfig(ssid: String, pws: String?): WifiConfiguration {
val config = WifiConfiguration()
config.allowedAuthAlgorithms.clear()
config.allowedGroupCiphers.clear()
config.allowedKeyManagement.clear()
config.allowedPairwiseCiphers.clear()
config.allowedProtocols.clear()
config.SSID = "\"" + ssid + "\""
if (pws.isNullOrEmpty()) {
FdageLog.i(TAG, " [getWifiConfig] 网络:$ssid 无密码连接")
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE)
} else {
FdageLog.i(TAG, " [getWifiConfig] 网络:$ssid 密码:$pws 连接")
config.preSharedKey = "\"" + pws + "\""
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
}
使用getWifiConfig方法设置好WifiConfiguration数据
然后使用WifiConfiguration数据,直接连接
FdageLog.i(TAG, " [connectWifi] 低版本 开始连接${wifiInfo.SSID}")
var wifiManager: WifiManager = activity.getSystemService(Context.WIFI_SERVICE) as WifiManager
val wifiConfig = getWifiConfig(wifiInfo.SSID, password)
val netId = wifiManager!!.addNetwork(wifiConfig)
wifiManager!!.enableNetwork(netId, true)
低版本连接还是比较简单直接的,经测试基本能连接成功
android 10以上高版本连接
方式一:使用WifiNetworkSuggestion实现
@RequiresApi(Build.VERSION_CODES.Q)
fun connect2(wifiInfo: ScanResult, password: String?) {
Log.d(TAG, " [connect2] removeNetworkSuggestions")
val suggestion = if (password.isNullOrEmpty()) {
WifiNetworkSuggestion.Builder()
.setSsid(wifiInfo.SSID)
.setBssid(MacAddress.fromString(wifiInfo.BSSID))
.build()
} else if (wifiInfo.capabilities.contains("wpa3", true)) {
Log.d(TAG, " [connect2] 高版本 创建 wpa3类型 ${wifiInfo.SSID} 网络配置")
WifiNetworkSuggestion.Builder()
.setSsid(wifiInfo.SSID)
.setBssid(MacAddress.fromString(wifiInfo.BSSID))
.setWpa3Passphrase(password)
// Optional (Needs location permission)
.build()
} else {
Log.d(TAG, " [connect2] 高版本 创建 其他类型 ${wifiInfo.SSID} 网络配置")
WifiNetworkSuggestion.Builder()
.setSsid(wifiInfo.SSID)
.setBssid(MacAddress.fromString(wifiInfo.BSSID))
.setWpa2Passphrase(password)
// Optional (Needs location permission)
.build()
}
val suggestionsList = listOf(suggestion)
val status = wifiManager.addNetworkSuggestions(suggestionsList)
if (status == WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
Log.d(TAG, " [connect2] 高版本 addNetworkSuggestions返回成功")
} else {
// do error handling here
Log.d(TAG, " [connect2] 高版本 addNetworkSuggestions返回失败")
}
}
注释都解释了各个步骤的操作,这种方式是向系统提供一个可连接网络的建议,系统会自行判断连接哪个网络:官网解释
经测试:除非手机一个能连接的wifi都没有,系统会连接我们提供的这个wifi,这种方式连接成功的所有app能正常访问网络
方式二:使用WifiNetworkSpecifier连接
@RequiresApi(Build.VERSION_CODES.Q)
fun higherVersionConnectWifi(wifiInfo: ScanResult, password: String?) {
val specifier = if (password.isNullOrEmpty()) {
WifiNetworkSpecifier.Builder()
.setSsid(wifiInfo.SSID)
.setBssid(MacAddress.fromString(wifiInfo.BSSID))
.build()
} else if (wifiInfo.capabilities.contains("wpa3", true)) {
WifiNetworkSpecifier.Builder()
.setSsid(wifiInfo.SSID)
.setBssid(MacAddress.fromString(wifiInfo.BSSID))
.setWpa3Passphrase(password)
.build()
} else {
WifiNetworkSpecifier.Builder()
.setSsid(wifiInfo.SSID)
.setBssid(MacAddress.fromString(wifiInfo.BSSID))
.setWpa2Passphrase(password)
.build()
}
val request = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.setNetworkSpecifier(specifier)
.build()
var connectivityManager = activity.getSystemService(Context.WIFI_SERVICE) as WifiManager
val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
// do success processing here..
FdageLog.i(TAG, " [higherVersionConnectWifi] 高版本 onAvailable 连接成功")
//绑定网络,否则无法访问网络
connectivityManager?.bindProcessToNetwork(network)
}
override fun onUnavailable() {
// do failure processing here..
FdageLog.i(TAG, " [higherVersionConnectWifi] 高版本 onUnavailable 连接失败")
isConnecting = false
}
}
connectivityManager?.requestNetwork(request, networkCallback)
}
这种方式是点对点的强连接,经测试:基本能够实现强制连接目标wifi,缺点是只能是app本身能访问wifi网络,手机其他app是用不了该网络的,而且app在后台结束后连接也会断开
官网也有详细的说明