问题描述:在连接设备热点的开发中,使用WifiNetworkSpecifier连上设备热点,再切换回原网络后,http请求一直报SocketException: Connection failed (OS Error: Machine is not on the network, errno = 64)
Android 10 中需要使用新的网络连接api WifiNetworkSpecifier ---
val specifier = WifiNetworkSpecifier.Builder()
.setSsidPattern(PatternMatcher(deviceid, PatternMatcher.PATTERN_LITERAL))
.build()
val request = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
//.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
//.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)//网络不受限
//.addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)//信任网络,增加这个参数让设备连接wifi之后还联网。
.setNetworkSpecifier(specifier)
.build()
connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
connectivityManager.bindProcessToNetwork(network)
Log.i("wifi", "connect success")
}
override fun onUnavailable() {
super.onUnavailable()
Log.i("wifi", "connect faild")
}
}
connectivityManager.registerNetworkCallback(request, networkCallback)
connectivityManager.requestNetwork(request, networkCallback)
分析:在使用WifiNetworkSpecifier 连接时修改了网络配置,导致切换回原网络时,环境发生了改变,但没有重置网络配置,导致请求失败。
原因:使用 WifiNetworkSpecifier请求连接目标network时,在requestNetwork绑定NetworkCallback中,我们需要使用bindProcessToNetwork将当前进程绑定到连接的网络上,确保所有的请求连接绑定在目标network上,才能在目标netwoek上正常请求网络,因此在切换回原网络后,如未重置配置,当前app进程的所有http请求都将继续在目标network上继续进行,即使断开了连接。如果network断开连接,以这种方式创建的所有Socket都将停止工作,并且所有主机名解析都将失败。这是设计使然,app认为仍绑定到特定Network. 所以要清除绑定,使用null重新绑定network。
fun unregisterNetWork() {
connectivityManager.bindProcessToNetwork(null)
connectivityManager.unregisterNetworkCallback(networkCallback)
}