改造不适用于特定版本的android

时间:2019-04-06 08:28:17

标签: java android retrofit retrofit2

我在运行Android 4.3的模拟器上存在Retrofit问题,并且设备在Android 4.4.2上存在问题,而相同的代码通常在装有Android 7.1.1的另一个模拟器上正常运行

每次尝试执行get请求时,都会收到超时异常。

java.net.SocketTimeoutException: failed to connect to jsonplaceholder.typicode.com/2606:4700:30::681c:3f5 (port 443) after 10000ms
        at libcore.io.IoBridge.connectErrno(IoBridge.java:159)
        at libcore.io.IoBridge.connect(IoBridge.java:112)
        at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
        at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)
        at java.net.Socket.connect(Socket.java:842)
        at okhttp3.internal.platform.AndroidPlatform.connectSocket(AndroidPlatform.java:73)
        at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.java:246)
        at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:166)
        at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:257)
        at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135)
        at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114)
        at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
        at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
        at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
        at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
        at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:254)
        at okhttp3.RealCall$AsyncCall.execute(RealCall.java:200)
        at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
        at java.lang.Thread.run(Thread.java:841)

代码在下面

public interface Api {
    String BASE_URL = "https://jsonplaceholder.typicode.com/";

    @GET("posts")
    Call<ArrayList<Post>> getPosts();
}

和对api的调用

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(Api.BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build();

Api api = retrofit.create(Api.class);
Call<ArrayList<Post>> call = api.getPostes();
Log.i("RequestUrl", call.request().url().toString());
call.enqueue(new Callback<ArrayList<Post>>() {
    @Override
    public void onResponse(Call<ArrayList<Post>> call, Response<ArrayList<Post>> response) {
        mPostsList.setValue(response.body());
    }

    @Override
    public void onFailure(Call<ArrayList<Post>> call, Throwable t) {
        Log.e("Posts", "Error occurred", t);
    }
});

3 个答案:

答案 0 :(得分:11)

它显示为java.net.SocketTimeoutException,起初建议提高客户端的连接超时值,正如本answer中所解释的那样-但是在查看{{ 1}} ...这暗示了不兼容的协议。

服务器的source code支持okhttp3.internal.platform.AndroidPlatform,这是Android 4.x所必需的(它们没有问题);问题在于,当前的TLS 1.0版本不再支持OkHttp3,因此握手将永远不会发生(这就是为什么它会产生误导性的TLS 1.0而不是SocketTimeoutException


对于SSLHandshakeException OkHttp3,默认配置3.12.x-

仍应支持它

但有人可以指示MODERN_TLS OkHttp3改用配置3.13.x

COMPATIBLE_TLS

还必须将其设置为/* ConnectionSpec.MODERN_TLS is the default value */ List tlsSpecs = Arrays.asList(ConnectionSpec.MODERN_TLS); /* providing backwards-compatibility for API lower than Lollipop: */ if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { tlsSpecs = Arrays.asList(ConnectionSpec.COMPATIBLE_TLS); } OkHttpClient client = new OkHttpClient.Builder() .connectionSpecs(tlsSpecs) .build(); 的客户端:

Retrofit

有关Retrofit retrofit = new Retrofit.Builder() .baseUrl(Api.BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .setClient(client) .build(); 版本的可用协议支持,请参见SSL certificate。看来OkHttp3甚至已经支持3.12.x,因为将来Android TLS 1.3会需要Q。甚至不需要降级OkHttp3,因为MODERN_TLS中的3.12.x仍支持TLSv1,而在3.13.x中它已移至{{ 1}};仍不确定COMPATIBLE_TLS

即使使用当前的3.14.x版本,也可能仍可以将所需的OkHttp3协议重新添加到TLS 1.0中,因为这是使用方法{{1 }}-在没有任何保证的情况下,不会再出现不兼容的情况; ConnectionSpec.COMPATIBLE_TLS可能仍然是支持Android 4.x及更高版本的最佳选择,甚至可能会有一些较新功能的后退。

答案 1 :(得分:1)

21之前的Android缺少一些SSL,无法进行翻新。使用Google服务,您可以在HTTP请求生效后更新设备协议

    //compile 'com.google.android.gms:play-services-base:11.0.0'
     //remember to add the library in your dependencies

        //compile 'com.google.android.gms:play-services-base:$currentVersion'

        ProviderInstaller.installIfNeededAsync(this, new ProviderInstallListener() {

            @Override

            public void onProviderInstalled() {

                //Do your http request here

            }


            @Override

            public void onProviderInstallFailed(int errorCode, Intent recoveryIntent) {

                //sad face :C is sad

            }

        });

答案 2 :(得分:0)

         If you use android 9 (Pie) or android SDK above 28 and get the issue on over the api call through Retrofit. add this below line into the manifest.xml file between the <application>.




    [enter link description here][1]android:usesCleartextTraffic="true"


  [1]: Refer this link this line work for me https://github.com/square/retrofit/issues/2925