【问题标题】:How do I get Codenameone android App to reliably connect to REST API?如何让 Codenameone android App 可靠地连接到 REST API?
【发布时间】:2021-10-16 14:59:40
【问题描述】:

我已经构建了一个代号为一个使用 REST 连接 restdb.io 数据库后端的 Android 应用程序。但是,我遇到如下随机网络故障

>     [EDT] 0:4:26,949 - Exception: java.net.ConnectException - Failed to connect to ziemozi-a3ef.restdb.io/188.166.28.84:443
> java.net.ConnectException: Failed to connect to
> ziemozi-a3ef.restdb.io/188.166.28.84:443  at
> com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:147)
>   at
> com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:116)
>   at
> com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:186)
>   at
> com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:128)
>   at
> com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:97)
>   at
> com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:302)
>   at
> com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:245)
>   at
> com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:465)
>   at
> com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:411)
>   at
> com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:542)
>   at
> com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:106)
>   at
> com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:30)
>   at
> com.codename1.impl.android.AndroidImplementation.getResponseCode(AndroidImplementation.java:6113)
>   at
> com.codename1.io.ConnectionRequest.performOperationComplete(ConnectionRequest.java:905)
>   at
> com.codename1.io.NetworkManager$NetworkThread.run(NetworkManager.java:341)
>   at
> com.codename1.impl.CodenameOneThread$1.run(CodenameOneThread.java:60)
>   at java.lang.Thread.run(Thread.java:919)

或

> java.net.SocketTimeoutException: timeout
    at com.android.okhttp.okio.Okio$3.newTimeoutException(Okio.java:214)
    at com.android.okhttp.okio.AsyncTimeout.exit(AsyncTimeout.java:263)
    at com.android.okhttp.okio.AsyncTimeout$2.read(AsyncTimeout.java:217)
    at com.android.okhttp.okio.RealBufferedSource.indexOf(RealBufferedSource.java:307)
    at com.android.okhttp.okio.RealBufferedSource.indexOf(RealBufferedSource.java:301)
    at com.android.okhttp.okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:197)
    at com.android.okhttp.internal.http.Http1xStream.readResponse(Http1xStream.java:188)
    at com.android.okhttp.internal.http.Http1xStream.readResponseHeaders(Http1xStream.java:129)
    at com.android.okhttp.internal.http.HttpEngine.readNetworkResponse(HttpEngine.java:770)
    at com.android.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:642)
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:475)
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:411)
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:542)
    at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:106)
    at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:30)
    at com.codename1.impl.android.AndroidImplementation.getResponseCode(AndroidImplementation.java:6113)
    at com.codename1.io.ConnectionRequest.performOperationComplete(ConnectionRequest.java:905)
    at com.codename1.io.NetworkManager$NetworkThread.run(NetworkManager.java:341)
    at com.codename1.impl.CodenameOneThread$1.run(CodenameOneThread.java:60)
    at java.lang.Thread.run(Thread.java:919)
Caused by: java.net.SocketException: socket is closed
    at com.android.org.conscrypt.ConscryptFileDescriptorSocket$SSLInputStream.read(ConscryptFileDescriptorSocket.java:554)
    at com.android.okhttp.okio.Okio$2.read(Okio.java:138)
    at com.android.okhttp.okio.AsyncTimeout$2.read(AsyncTimeout.java:213)

这在模拟器和设备中都会发生。并且在使用固定互联网或移动互联网时,虽然它似乎更多地发生在移动互联网上,

【问题讨论】:

    标签: codenameone


    【解决方案1】:

    您报告的两个日志似乎都涉及连接问题,而不是服务器端错误。您无法避免连接问题,事实上,您应该假设它们是正常的,尤其是在移动设备上。那么问题是如何处理它们。

    没有普遍有效的答案,这取决于您想要实现的目标。在这些情况下,许多应用程序所做的是向用户报告问题,同时不断尝试重复失败的操作,即在本例中为 REST 请求,直到收到 HTTP 代码作为响应。

    对于这种方法,我曾经问过一个问题,你可以在这里阅读:Distinguish between server-side errors and connection problems

    简而言之,我从 init() 中删除了默认的错误处理代码,并为此目的调用了以下经过良好测试和工作的方法(它是基于 Distinguish between server-side errors and connection problems 中代码的版本),您可以根据满足您的需求:

        private void addNetworkAndServerErrorListener() {
            // The following way to manage network errors is discussed here:
            // https://stackoverflow.com/questions/61993127/distinguish-between-server-side-errors-and-connection-problems
            addNetworkErrorListener(err -> {
                // prevents the event from propagating
                err.consume();
    
                if (err.getError() != null) {
                    // this is the case of a network error,
                    // like: java.io.IOException: Unreachable
                    Log.p("Error connectiong to: " + err.getConnectionRequest().getUrl(), Log.ERROR);
                    // maybe there are connectivity issues, let's try again
                    ToastBar.showInfoMessage("Reconnect...");
                    Timer timer = new Timer();
                    timer.schedule(new TimerTask() {
                        @Override
                        public void run() {
                            err.getConnectionRequest().retry();
                        }
                    }, 2000);
                } else {
                    // this is the case of a server error
                    // logs the error
                    String errorLog = "REST ERROR\nURL:" + err.getConnectionRequest().getUrl()
                            + "\nMethod: " + err.getConnectionRequest().getHttpMethod()
                            + "\nResponse code: " + err.getConnectionRequest().getResponseCode();
                    if (err.getConnectionRequest().getRequestBody() != null) {
                        errorLog += "\nRequest body: " + err.getConnectionRequest().getRequestBody();
                    }
                    if (err.getMetaData() != null) {
                        errorLog += "\nMetaData: " + err.getMetaData().toString();
                    }
                    if (err.getConnectionRequest().getResponseData() != null) {
                        errorLog += "\nResponse message: " + new String(err.getConnectionRequest().getResponseData());
                    }
                    if (err.getConnectionRequest().getResponseErrorMessage() != null) {
                        errorLog += "\nResponse error message: " + err.getConnectionRequest().getResponseErrorMessage();
                    }
                    if (err.getMessage() != null) {
                        errorLog += "\nResponse error message: " + err.getMessage();
                    }
                    Log.p(errorLog, Log.ERROR);
    
                    Log.sendLogAsync();
                    ToastBar.showErrorMessage("Server Error", 10000);
                }
            });
        }
    

    【讨论】:

    • 让我试试看。
    猜你喜欢
    • 1970-01-01
    • 2017-02-08
    • 2014-01-14
    • 1970-01-01
    • 2018-10-07
    • 1970-01-01
    • 1970-01-01
    • 2014-09-24
    • 2015-11-21
    相关资源
    最近更新 更多