53

I am trying to POST request to server for fetch data but sometime It's occure SocketTimeoutException!

I used Ok3Client to resolve it but I facing the same Exception How can I resolve it?

My code is below

public void getNormalLogin() {
        if (mProgressDialog == null) {
            mProgressDialog = ViewUtils.createProgressDialog(mActivity);
            mProgressDialog.show();
        } else {
            mProgressDialog.show();
        }

        if (Build.VERSION.SDK != null && Build.VERSION.SDK_INT > 13) {
            restadapter = new RestAdapter.Builder().setEndpoint(HOST).setLogLevel(RestAdapter.LogLevel.FULL).setClient(new Ok3Client(new OkHttpClient())).build();
            mApi = restadapter.create(Api.class);
            mApi.SignIn(etEmail.getText().toString(), etPassword.getText().toString(), new Callback<ArrayList<SignUpMainBean>>() {
                @Override
                public void success(ArrayList<SignUpMainBean> signUpMainBeen, Response response) {
                    mProgressDialog.dismiss();
                    LOGD("Status:: ::", String.valueOf(response.getStatus()));
                    LOGD("Code:: ::", String.valueOf(signUpMainBeen.get(0).getCode()));
                    if (signUpMainBeen != null && signUpMainBeen.size() > 0) {
                        if (signUpMainBeen.get(0).getCode() == 1) {

                            for (int i = 0; i < signUpMainBeen.size(); i++) {
                                for (int j = 0; j < signUpMainBeen.get(i).getResult().size(); j++) {
                                    showToast(mActivity, getString(R.string.you_have_successfully_login), Toast.LENGTH_SHORT);
                                    LOGD("Success", "Success");                                                                         
                                   finish();
                                    SignIn.mActivity.finish();
                                }
                            }

                        } else if (signUpMainBeen.get(0).getCode() == 0) {
                            mProgressDialog.dismiss();
                            showToast(mActivity, getString(R.string.invalid_email_password), Toast.LENGTH_SHORT);
                            LOGD("Invalid email or password", "Invalid email or password");
                        } else if (signUpMainBeen.get(0).getCode() == -1) {
                            mProgressDialog.dismiss();
                            showToast(mActivity, getString(R.string.your_account_is_inactive), Toast.LENGTH_SHORT);
                            LOGD("Your account is inactive", "Your account is inactive");
                        }
                    }
                }

                @Override
                public void failure(RetrofitError error) {
                    mProgressDialog.dismiss();
                    showToast(mActivity, getString(R.string.can_not_connect_to_server), Toast.LENGTH_SHORT);
                    LOGD("Failure", "Failure");
                }
            });
        }
    }

My Error Log is

D/Retrofit: java.net.SocketTimeoutException
at java.net.PlainSocketImpl.read(PlainSocketImpl.java:532)
at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:40)
at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:255)
at okio.Okio$2.read(Okio.java:139)
at okio.AsyncTimeout$2.read(AsyncTimeout.java:211)
at okio.RealBufferedSource.indexOf(RealBufferedSource.java:306)
at okio.RealBufferedSource.indexOf(RealBufferedSource.java:300)
at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:196)
at okhttp3.internal.http.Http1xStream.readResponse(Http1xStream.java:185)
at okhttp3.internal.http.Http1xStream.readResponseHeaders(Http1xStream.java:126)
at okhttp3.internal.http.HttpEngine.readNetworkResponse(HttpEngine.java:723)
at okhttp3.internal.http.HttpEngine.access$200(HttpEngine.java:81)
at okhttp3.internal.http.HttpEngine$NetworkInterceptorChain.proceed(HttpEngine.java:708)
at okhttp3.internal.http.HttpEngine.readResponse(HttpEngine.java:563)
at okhttp3.RealCall.getResponse(RealCall.java:241)
at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:198)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:160)
at okhttp3.RealCall.execute(RealCall.java:57)
at com.jakewharton.retrofit.Ok3Client.execute(Ok3Client.java:40)
at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:326)
at retrofit.RestAdapter$RestHandler.access$100(RestAdapter.java:220)
at retrofit.RestAdapter$RestHandler$2.obtainResponse(RestAdapter.java:278)
at retrofit.CallbackRunnable.run(CallbackRunnable.java:42)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at retrofit.Platform$Android$2$1.run(Platform.java:142)
at java.lang.Thread.run(Thread.java:818)
USER9561
  • 1,084
  • 3
  • 15
  • 41
  • Possible duplicate of [Getting java.net.SocketTimeoutException: Connection timed out in android](http://stackoverflow.com/questions/15608499/getting-java-net-sockettimeoutexception-connection-timed-out-in-android) – Soham Aug 30 '16 at 06:11
  • 1
    @Komal how to stop crash? Did you find any solution? Please share.. – Bhavin Patel Jun 21 '17 at 07:22

6 Answers6

84

Increase the time if the fetching is taking more time use this code it worked for me

 OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(100, TimeUnit.SECONDS)
            .readTimeout(100,TimeUnit.SECONDS).build();
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("yourbaseurl").client(client)
            .addConverterFactory(GsonConverterFactory.create(new  Gson())).build();

hay this is a work around not the best practice , from comments down, Back end should not take this long and user must be notified with error or try again message

3bdoelnaggar
  • 1,109
  • 8
  • 18
  • 9
    This doesn't prevent the app crash in our application. Is there a way to handle this without having the app crash? – Marco RS Apr 10 '17 at 12:10
  • what Exception do you get is it Null Pointer – 3bdoelnaggar Apr 10 '17 at 18:52
  • 1
    Your application will try to load the content even if the server is responding after a long time - It's a workaround, not the solution :) – tryp May 23 '17 at 14:34
  • 2
    Even for a workaround this is bad. Increasing the Timeout will do nothing to solve the issue. There is no way to prevent a Timeout, it will always happen wether the API takes time to respond or connectivity is bad. Best bet is to catch this and prompt to the user something went wrong and ask them to try again. If the actual API calls takes time and the bottleneck is on the backend side you may want to consider looking into that. APIs should be fast and anything more than 10s where the API is the culprit is just bad. – Placeable Jan 23 '19 at 14:08
42

Preventing SocketTimeoutException is beyond our limit...One way to effectively handle it is to define a connection timeout

Example for

retrofit 1.9.0

restadapter = new RestAdapter.Builder().setEndpoint(HOST).setLogLevel(RestAdapter.LogLevel.FULL).setClient(new OkHttpClient()
                .setReadTimeout(30, TimeUnit.SECONDS)
                .setConnectTimeout(30, TimeUnit.SECONDS)).build();

retrofit 2.0.0

OkHttpClient client = new OkHttpClient();
client.setConnectTimeout(10, TimeUnit.SECONDS);
client.setReadTimeout(30, TimeUnit.SECONDS);
retrofit = new Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .client(client)
        .build();

retrofit 2.4.0

// setting custom timeouts
    OkHttpClient.Builder client = new Builder();
    client.connectTimeout(15, TimeUnit.SECONDS);
    client.readTimeout(15, TimeUnit.SECONDS);
    client.writeTimeout(15, TimeUnit.SECONDS);

    if (retrofit == null) {
      retrofit = new Retrofit.Builder()
          .baseUrl(BASE_URL)
          .addConverterFactory(GsonConverterFactory.create())
          .client(client.build())
          .build();
    }
    return retrofit;
  }
ashishdhiman2007
  • 807
  • 2
  • 13
  • 28
Soham
  • 4,397
  • 11
  • 43
  • 71
  • 1
    Can not resolve method of readTimeout(30, TimeUnit.SECONDS) and connectTimeout(30, TimeUnit.SECONDS)).build(); –  Aug 30 '16 at 06:22
  • Are you using `'com.squareup.okhttp3:okhttp:3.4.1'` @Komal – Soham Aug 30 '16 at 06:27
  • I'm using compile 'com.squareup.okhttp3:okhttp:3.0.0' –  Aug 30 '16 at 06:28
  • I also tried 'com.squareup.okhttp3:okhttp:3.4.1' but still as it is!!! Any other idea about it? –  Aug 30 '16 at 06:33
  • @Komal You are using retrofit right ?What is the version of it. – Soham Aug 30 '16 at 06:37
  • I used these both compile 'com.squareup.retrofit:retrofit:1.9.0' compile 'com.jakewharton.retrofit:retrofit1-okhttp3-client:1.0.2' –  Aug 30 '16 at 06:39
  • @Komal I gave you the example for retrofit 2.0 .Please check my updated answer I have changed. – Soham Aug 30 '16 at 06:42
  • Thanks @Soham but still setReadTimeout(30, TimeUnit.SECONDS) not resolved method –  Aug 30 '16 at 06:45
  • @Komal please check again my answer.I forgot mostly the code for retrofit 1.9.0 – Soham Aug 30 '16 at 06:58
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/122166/discussion-between-komal-and-soham). –  Aug 30 '16 at 07:01
  • @Komal Please check [this](http://stackoverflow.com/a/29380845/3967525) – Soham Aug 30 '16 at 07:06
  • How to set the timeout in Retrofit `2.1.0`? – Shajeel Afzal Oct 30 '16 at 12:13
  • 2
    Set it on the builder and not on the client. OkHttpClient.Builder() .readTimeout(60, TimeUnit.SECONDS) .connectTimeout(60, TimeUnit.SECONDS) – Teffi Sep 13 '17 at 11:14
13

I'm facing the same issue with some request. Usually get this when there's an active request and got SocketTimeoutException due to got disconnected from the network. After that, same request always throws SocketTimeoutException.

I built my OkHttpClient using the code below as suggested in "java.net.SocketTimeoutException from HTTP/2 connection leaves dead okhttp clients in pool":

val builder = OkHttpClient.Builder()
    .cache(cache)
    .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
    .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
    .connectionPool(ConnectionPool(0, 5, TimeUnit.MINUTES))
    .protocols(listOf(Protocol.HTTP_1_1))

Setting the connectionPool and protocols will fix SocketTimeoutException caused by Timeouts.

This is a temporary fix and hopefully will get resolved in future versions of OkHttp used by Retrofit.

Philip Borbon
  • 707
  • 1
  • 11
  • 21
  • Adding protocol HTTP_1_1 worked! Thanks @philip. This is what I got from sourcecode- /** * An obsolete plaintext framing that does not use persistent sockets by default. */ HTTP_1_0("http/1.0"), /** * A plaintext framing that includes persistent connections. * *

    This version of OkHttp implements RFC * 7230, and tracks revisions to that spec. */ HTTP_1_1("http/1.1"),

    – Sumit Jan 08 '20 at 07:25
  • 1
    This saved me from the hours of waste. Thank you so much dude and the dude who gave this solution to you. – Subhasmith Thapa Mar 26 '21 at 14:03
2
val builder = OkHttpClient.Builder()
.cache(cache)
.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
.connectionPool(ConnectionPool(0, 5, TimeUnit.MINUTES))
.protocols(listOf(Protocol.HTTP_1_1))

ConnectionPool(0, 5, TimeUnit.MINUTES) is key code, set maxIdleConnections as 0, to avoid the SocketTimeoutException by multiplex. this case is easy to happen when locking/unlocking the screen.

1

It's works for me to catch and throw a new IOException

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Response response = null;
        try {
            response = chain.proceed(request);
        }catch (SocketTimeoutException e){
            throw new IOException();
        }
        String url = request.url().url().toString();
        if (existInWhiteList(url)) {
            return response;
        }
        return logResponse(response);
    }

and you can add your own info in this new IOException();

jiar wang
  • 360
  • 2
  • 12
0

A possible resolution for this is make sure that you sending the correct request body to the server. For example, does the server need x-www-form-urlencoded or form-data in its request body? A simple way to test this is using Postman.

hexicle
  • 2,121
  • 2
  • 24
  • 31