Internet断开后Retrofit2 Singleton导致失败的http请求

时间:2018-06-21 21:47:39

标签: android retrofit2

我正在尝试使用超简单单例创建翻新服务。这似乎在大多数时间都有效。例外,当我通过打开飞行模式测试连接断开时,http请求将按原样失败。但是当我关闭飞行模式时,请求将继续失败。我收到此错误: HTTP FAILED: java.net.SocketTimeoutException: timeout

这是我正在使用的代码:

class ServiceGenerator {
    private static ScanClient service = null;

    static ScanClient createService(Class<ScanClient> serviceClass, Context context) {
        if (service == null) {
            String apiBaseUrl = Constants.RETROFIT_BASE_URL;
            Retrofit.Builder builder = new Retrofit.Builder()
                .baseUrl(apiBaseUrl)
                .addConverterFactory(GsonConverterFactory.create());

            OkHttpClient.Builder httpClient = new OkHttpClient.Builder();

            if (Constants.PHP_DEBUG) {
                HttpLoggingInterceptor logging = new HttpLoggingInterceptor()
                    .setLevel(HttpLoggingInterceptor.Level.BODY);

                httpClient.addInterceptor(logging);
            }

            httpClient.addInterceptor(new ReceivedCookiesInterceptor(context));
            httpClient.addInterceptor(new AddCookiesInterceptor(context));
            builder.client(httpClient.build());
            Retrofit retrofit = builder.build();

            service = retrofit.create(serviceClass);
        }

        return service;
    }
}

2 个答案:

答案 0 :(得分:0)

您可以通过处理超时来做到这一点。

        ...
        OkHttpClient.Builder httpClient = new OkHttpClient.Builder();

        if (Constants.PHP_DEBUG) {
            HttpLoggingInterceptor logging = new HttpLoggingInterceptor()
                .setLevel(HttpLoggingInterceptor.Level.BODY);

            httpClient.addInterceptor(logging);
        }

        httpClient.connectTimeout(2, TimeUnit.MINUTES);
        httpClient.writeTimeout(2, TimeUnit.MINUTES);
        httpClient.readTimeout(2, TimeUnit.MINUTES);
        httpClient.addInterceptor(new ReceivedCookiesInterceptor(context));
        httpClient.addInterceptor(new AddCookiesInterceptor(context));
        builder.client(httpClient.build());
        ...

答案 1 :(得分:0)

我不确定这是最好的解决方案,但是设置新的sslSocketFactory可以帮助

OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
clientBuilder.eventListener(new EventListener() {
        @Override
        public void callStart(Call call) {
            super.callStart(call);
        }

        @Override
        public void dnsStart(Call call, String domainName) {
            super.dnsStart(call, domainName);
        }

        @Override
        public void dnsEnd(Call call, String domainName, List<InetAddress> inetAddressList) {
            super.dnsEnd(call, domainName, inetAddressList);
        }

        @Override
        public void connectStart(Call call, InetSocketAddress inetSocketAddress, Proxy proxy) {
            super.connectStart(call, inetSocketAddress, proxy);
        }

        @Override
        public void secureConnectStart(Call call) {
            super.secureConnectStart(call);
        }

        @Override
        public void secureConnectEnd(Call call, Handshake handshake) {
            super.secureConnectEnd(call, handshake);
        }

        @Override
        public void connectEnd(Call call, InetSocketAddress inetSocketAddress, Proxy proxy, Protocol protocol) {
            super.connectEnd(call, inetSocketAddress, proxy, protocol);
        }

        @Override
        public void connectFailed(Call call, InetSocketAddress inetSocketAddress, Proxy proxy, Protocol protocol, IOException ioe) {
            super.connectFailed(call, inetSocketAddress, proxy, protocol, ioe);
        }

        @Override
        public void connectionAcquired(Call call, Connection connection) {
            super.connectionAcquired(call, connection);
        }

        @Override
        public void connectionReleased(Call call, Connection connection) {
            super.connectionReleased(call, connection);
        }

        @Override
        public void requestHeadersStart(Call call) {
            super.requestHeadersStart(call);
        }

        @Override
        public void requestHeadersEnd(Call call, Request request) {
            super.requestHeadersEnd(call, request);
        }

        @Override
        public void requestBodyStart(Call call) {
            super.requestBodyStart(call);
        }

        @Override
        public void requestBodyEnd(Call call, long byteCount) {
            super.requestBodyEnd(call, byteCount);
        }

        @Override
        public void responseHeadersStart(Call call) {
            super.responseHeadersStart(call);
        }

        @Override
        public void responseHeadersEnd(Call call, Response response) {
            super.responseHeadersEnd(call, response);
        }

        @Override
        public void responseBodyStart(Call call) {
            super.responseBodyStart(call);
        }

        @Override
        public void responseBodyEnd(Call call, long byteCount) {
            super.responseBodyEnd(call, byteCount);
        }

        @Override
        public void callEnd(Call call) {
            super.callEnd(call);
        }

        @Override
        public void callFailed(Call call, IOException ioe) {
            super.callFailed(call, ioe);

            if (ioe instanceof SocketTimeoutException) {
                reInitSslSocketFactory();
            }
        }
    });

reInitSslSocketFactory方法:

private void reInitSslSocketFactory() {
    try {
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
                TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init((KeyStore) null);
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
            throw new IllegalStateException("Unexpected default trust managers:"
                    + Arrays.toString(trustManagers));
        }

        SSLContext sslContext = Platform.get().getSSLContext();
        X509TrustManager trustManager = (X509TrustManager) trustManagers[0];

        sslContext.init(null, new TrustManager[]{trustManager}, null);

        OkHttpClient okHttpClient = ((OkHttpClient) retrofit.callFactory()).newBuilder()
                .sslSocketFactory(sslContext.getSocketFactory(), trustManager)
                .build();
        retrofit = retrofit.newBuilder().client(okHttpClient).build();
    } catch (GeneralSecurityException e) {
        throw assertionError("No System TLS", e); // The system has no TLS. Just give up.
    }
}