改造不适用于特定版本的android [英] Retrofit not working on specific versions of android
问题描述
我在运行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);
}
});
它读取java.net.SocketTimeoutException
,起初建议提高客户端的连接超时值,如以下okhttp3.internal.platform.AndroidPlatform的/java/okhttp3/internal/platform/AndroidPlatform.kt"rel =" noreferrer>源代码 ...这暗示了不兼容的协议.
服务器的 TLS配置历史记录. OkHttp3
版本.似乎3.12.x
甚至已经支持TLS 1.3
,因为将来Android Q
会要求它.甚至不需要降级OkHttp3
,因为3.12.x
中的MODERN_TLS
仍然支持TLSv1
,而在3.13.x
中它已经移到了COMPATIBLE_TLS
中.仍然不确定3.14.x
.
即使使用当前版本的OkHttp3
,也可能仍可以将所需的TLS 1.0
协议重新添加到ConnectionSpec.COMPATIBLE_TLS
中,因为这是使用方法.add()
的ArrayList
-在没有任何保证的情况下,不会再出现不兼容的情况; 3.12.x
可能仍然是支持Android 4.x及更高版本的最佳选择,甚至可能会有一些较新功能的后端口.
I have a problem with Retrofit on my emulator running Android 4.3 and my device is on Android 4.4.2 while the same code runs normally on another emulator with Android 7.1.1
Each time I try to execute the get
request I get a timeout exception.
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)
The code is below
public interface Api {
String BASE_URL = "https://jsonplaceholder.typicode.com/";
@GET("posts")
Call<ArrayList<Post>> getPosts();
}
and the call to the 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);
}
});
It reads java.net.SocketTimeoutException
, which at first suggests to raise the client's connect-timeout value, as it is being explained in this answer - but when reviewing the current source code of okhttp3.internal.platform.AndroidPlatform
... this rather hints for incompatible protocols.
The server's SSL certificate supports TLS 1.0
, as it would be required for Android 4.x (there's no problem on their side); the problem rather is, that the current version of OkHttp3
does not support TLS 1.0
anymore and therefore the handshake won't ever take place (that's why it throws such a misleading SocketTimeoutException
instead of a SSLHandshakeException
).
With OkHttp3
3.12.x
, it should still be supported with the default configuration MODERN_TLS
-
but one could instruct OkHttp3
3.13.x
to use configuration COMPATIBLE_TLS
instead:
/* 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();
One also has to set it as the client for Retrofit
:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Api.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.setClient(client)
.build();
See the TLS Configuration History for the available protocol support, per OkHttp3
version. As it seems, 3.12.x
even already supports TLS 1.3
, as it will in future be required for Android Q
. It might not even be required to down-grade OkHttp3
, because MODERN_TLS
of 3.12.x
still supports TLSv1
, while in 3.13.x
it had been moved into COMPATIBLE_TLS
; still uncertain about 3.14.x
.
Even with current versions of OkHttp3
, one could possibly still add the desired TLS 1.0
protocol back into ConnectionSpec.COMPATIBLE_TLS
, since this is an ArrayList
with a method .add()
- without any guarantee, that there won't be further incompatibilities; 3.12.x
might still be the best choice for supporting Android 4.x onward and there might even be back-ports of newer features.
这篇关于改造不适用于特定版本的android的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!