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 提出的,我不知道为什么有人不赞成这个答案。没错。

有趣的是,如果我们通过设备设置连接到无互联网网络,即使没有绑定也能正常连接。