HttpURLConnection.connect() 在 Android 10 网络重新连接后失败
HttpURLConnection.connect() fails after network reconnection on Android 10
我的应用程序使用它的 WiFi 连接到外部设备(该设备用作服务器)。随着 Android 10 的引入,我需要为不同的平台实现单独的 WiFi 连接流(WifiNetworkSpecifier
用于 Android 10+,wifiManager.enableNetwork
用于 < Android 10)。连接流本身工作正常,但我在流通信方面遇到了一些问题。
在应用程序中,我可以将文件上传到该外部设备。为此,我需要使用 HttpURLConnection
。所以我 运行:
val url = URL(UPDATE_FIRMWARE_URL)
val connection = (url.openConnection() as HttpURLConnection)
with(connection) {
doInput = true
doOutput = true
useCaches = false
requestMethod = METHOD_POST
//setRequestProperty(HEADER_CONNECTION, "Keep-Alive")
setRequestProperty("Connection", "close")
connectTimeout = 6000
setRequestProperty(HEADER_USER_AGENT, "Android Multipart HTTP Client 1.0")
setRequestProperty(HEADER_CONTENT_TYPE, "multipart/form-data; boundary=$boundary")
}
connection.connect()
val outputStream = connection.outputStream
DataOutputStream(outputStream).use { outputStream ->
// actual file upload
}
现在,实际更新包含两个文件,第一次上传后设备重启,我需要重新连接到它的 wifi 并上传第二个文件。
在 Android < 9 时,整个上传流程(有两个文件)工作正常,但在 Android 10 时,在我发送第一个文件并重新连接到设备的 WiFi 后,当我调用 connection.connect()
我得到 ConnectExcpetion
内部原因 connect failed: ENETUNREACH (Network is unreachable)
(这真的没有意义,因为我连接到那个网络...)
java.net.ConnectException: Failed to connect to (...)
at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:1409)
at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:1359)
at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:221)
at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:144)
at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:106)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:400)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:333)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:483)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:135)
最初我在 Android 10 上第一次连接时也遇到了问题,但我找到了 this 文章,并添加了 connectTimeout 帮助,但现在我尝试时连接仍然失败第二次(以及以后每一次)连接。唯一有帮助的是重新启动整个应用程序(这不是真正的解决方案)。
可能是什么问题,下一个连接失败尽管我总是执行相同的代码?
几天后,我终于找到了问题的答案。事实证明,在 Android 10 上,当您连接到不提供互联网的接入点(例如我的外部设备)时,标准 API 调用(使用 Retrofit)工作正常,但是当尝试使用 HttpURLConnection
系统尝试使用某些网络连接到互联网,但由于有 none,连接失败。
连接工作的唯一方法是使用 ConnectivityManager.bindProcessToNetwork(network)
强制系统使用我们的网络。这个解决方案是 here 提出的,我不知道为什么有人不赞成这个答案。没错。
有趣的是,如果我们通过设备设置连接到无互联网网络,即使没有绑定也能正常连接。
我的应用程序使用它的 WiFi 连接到外部设备(该设备用作服务器)。随着 Android 10 的引入,我需要为不同的平台实现单独的 WiFi 连接流(WifiNetworkSpecifier
用于 Android 10+,wifiManager.enableNetwork
用于 < Android 10)。连接流本身工作正常,但我在流通信方面遇到了一些问题。
在应用程序中,我可以将文件上传到该外部设备。为此,我需要使用 HttpURLConnection
。所以我 运行:
val url = URL(UPDATE_FIRMWARE_URL)
val connection = (url.openConnection() as HttpURLConnection)
with(connection) {
doInput = true
doOutput = true
useCaches = false
requestMethod = METHOD_POST
//setRequestProperty(HEADER_CONNECTION, "Keep-Alive")
setRequestProperty("Connection", "close")
connectTimeout = 6000
setRequestProperty(HEADER_USER_AGENT, "Android Multipart HTTP Client 1.0")
setRequestProperty(HEADER_CONTENT_TYPE, "multipart/form-data; boundary=$boundary")
}
connection.connect()
val outputStream = connection.outputStream
DataOutputStream(outputStream).use { outputStream ->
// actual file upload
}
现在,实际更新包含两个文件,第一次上传后设备重启,我需要重新连接到它的 wifi 并上传第二个文件。
在 Android < 9 时,整个上传流程(有两个文件)工作正常,但在 Android 10 时,在我发送第一个文件并重新连接到设备的 WiFi 后,当我调用 connection.connect()
我得到 ConnectExcpetion
内部原因 connect failed: ENETUNREACH (Network is unreachable)
(这真的没有意义,因为我连接到那个网络...)
java.net.ConnectException: Failed to connect to (...)
at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:1409)
at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:1359)
at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:221)
at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:144)
at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:106)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:400)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:333)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:483)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:135)
最初我在 Android 10 上第一次连接时也遇到了问题,但我找到了 this 文章,并添加了 connectTimeout 帮助,但现在我尝试时连接仍然失败第二次(以及以后每一次)连接。唯一有帮助的是重新启动整个应用程序(这不是真正的解决方案)。
可能是什么问题,下一个连接失败尽管我总是执行相同的代码?
几天后,我终于找到了问题的答案。事实证明,在 Android 10 上,当您连接到不提供互联网的接入点(例如我的外部设备)时,标准 API 调用(使用 Retrofit)工作正常,但是当尝试使用 HttpURLConnection
系统尝试使用某些网络连接到互联网,但由于有 none,连接失败。
连接工作的唯一方法是使用 ConnectivityManager.bindProcessToNetwork(network)
强制系统使用我们的网络。这个解决方案是 here 提出的,我不知道为什么有人不赞成这个答案。没错。
有趣的是,如果我们通过设备设置连接到无互联网网络,即使没有绑定也能正常连接。