java - Android 库在捕获所有 Throwable 的 try block 内抛出异常

标签 java android kotlin

我们编写了一个 Kotlin 库来处理一些网络逻辑。该库本身包含一个 AsyncTask,它使用 java.net.* 中的 HttpURLConnection 设施。

private inner class ClickstreamTask(
                                    headers: HashMap<String, String>,
                                    params: Request,
                                    success: (() -> Unit)? = null,
                                    failure: ((statusCode: Int?, json: 
HashMap<String, String>?) -> Unit)? = null) : AsyncTask<Void, Unit, Unit>() {

    private var headers: HashMap<String, String> = headers
    private var paramaters: Request = params
    private var success: (() -> Unit)? = success
    private var failure: ((statusCode: Int?, json: HashMap<String, String>?) -> Unit)? = failure

    override fun doInBackground(vararg params: Void){

        val url = try {
            URL(getURLString() + path)
        } catch (e: Exception) {
            failure?.invoke(null, hashMapOf("error" to "Invalid URL."))
            return Unit
        }

        var request = try{
            url.openConnection() as HttpURLConnection
        } catch (e: Exception){
            failure?.invoke(null, hashMapOf("error" to "Unable to establish connection"))
            return Unit
        }

        request.doInput = false
        request.doOutput = true
        val mapper = jacksonObjectMapper()

        request.requestMethod = "POST"
        val httpBody = try {
            mapper.writeValueAsBytes(paramaters)
        } catch (e: Exception) {
            failure?.invoke(null, hashMapOf("error" to "Invalid params."))
            return Unit
        }

        for ((key, value) in headers) {
            request.setRequestProperty(key, value)
        }

        try{
            request.outputStream.write(httpBody)
        }catch (e: Throwable){
            request.outputStream.close()
            failure?.invoke(null, hashMapOf("error" to "Issue writing to URL"))
            return Unit
        }
        request.outputStream.close()


        if (request.responseCode != 200){
            failure?.invoke(request.responseCode, hashMapOf("Failed request" to request.responseMessage))
            return Unit
        }

        success?.invoke()
        return Unit
    }
}

当我们使用在飞行模式下运行该库的 Android 应用程序时,该应用程序会因未捕获的异常“UnknownHostException”而崩溃:

Caused by: java.net.UnknownHostException: Unable to resolve host "ste03lbclkapp00.iteclientsys.local": No address associated with hostname at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:141) at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:90) at java.net.InetAddress.getAllByName(InetAddress.java:787) at com.android.okhttp.Dns$1.lookup(Dns.java:39) at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:175) at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:141) at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:83) at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:174) at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:126) at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:95) at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:281) at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:224) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:461) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:127) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:258) at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getOutputStream(DelegatingHttpsURLConnection.java:218) at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getOutputStream(Unknown Source:0) at com.tdameritrade.amerivest.clickstreamshared.Network.NetworkManager$ClickstreamTask.doInBackground(NetworkManager.kt:87) at com.tdameritrade.amerivest.clickstreamshared.Network.NetworkManager$ClickstreamTask.doInBackground(NetworkManager.kt:43) at android.os.AsyncTask$2.call(AsyncTask.java:333) at java.util.concurrent.FutureTask.run(FutureTask.java:266) ... 4 more Caused by: android.system.GaiException: android_getaddrinfo failed: EAI_NODATA (No address associated with hostname) at libcore.io.Linux.android_getaddrinfo(Native Method) at libcore.io.ForwardingOs.android_getaddrinfo(ForwardingOs.java:59) at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:122) ... 24 more

引发异常的行是request.outputStream.write(httpBody)。但是,我们将该行包装在处理 Throwabletry/catch 中。

doOnBackground() 第 87 行包含在 catch 中时,它如何抛出异常?

最佳答案

这段代码:

    try{
        request.outputStream.write(httpBody)
    }catch (e: Throwable){
        request.outputStream.close()
        failure?.invoke(null, hashMapOf("error" to "Issue writing to URL"))
        return Unit
    }

将尝试在 catch block 中执行操作,这也可能生成异常:

        request.outputStream.close()

这是未被捕获的 - 但考虑到您在访问输出流时正在处理一些错误,这似乎也是不明智的。

异常跟踪表明了更多的原因,我猜进一步挖掘你会发现这个问题。

关于java - Android 库在捕获所有 Throwable 的 try block 内抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49984636/

相关文章:

Android studio 保持上传旧的apk版本

java - Android AsyncTask 类中的 NullPointerException

java - String.format 在 Kotlin 和 Java 中工作异常

gradle - 当我在gradle中添加新的源集时“Kotlin not configured”。 (IntelliJ)

Java 错误 - 找不到符号 "a"?

Java twitter OAuth,无法验证 oauth 签名

java - CSS 在 NetBeans 中与 java 应用程序一起使用

android - 如何在 EditText 上的 OK 上隐藏软键盘并再次显示

android - Kotlin 中键入后的单个感叹号 "!"是什么意思?

java - 在java中将数据从csv导入到snappy数据时出现错误