Android (Java) HttpURLConnection silent retry on 'read' timeout

前端 未结 4 863
春和景丽
春和景丽 2020-12-23 23:39

So I\'m using Google Volley for HTTP request, which basically uses Java\'s HttpURLConnection.

According to my tests, the

相关标签:
4条回答
  • 2020-12-23 23:56

    As it says in one of the links you quoted, you need to set sun.net.http.retryPost to false.

    Or, don't use fixed-length or chunked transfer mode: see this bug report.

    0 讨论(0)
  • 2020-12-24 00:09

    You can check out DefaultRetryPolicy class of Volley.

    0 讨论(0)
  • 2020-12-24 00:11

    This bad decision was made by a developer in the year 2006. Here is a nice citation from someone that explains the whole situation from java perspective:

    "As you probably guessed by now it's a bug (http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6382788). Not the retry mechanism, of course, that's just crap. The bug is that it also happens for a POST (which is by default not idempotent per HTTP RFC). But don't worry, Bill fixed that bug a long time ago. Bill fixed it by introducing a toggle. Bill learned about backward compatibility. Bill decided it's better to leave the toggle 'on' by default because that would make it bug-backward-compatible. Bill smiles. He can already see the faces of surprised developers around the globe running into this. Please don't be like Bill?"
    Source

    Well the proposed solution is:

    System.setProperty("sun.net.http.retryPost", "false")
    

    But we cannot do this on android! The only remaining solution then is:

    httpURLConnection.setChunkedStreamingMode(0);
    

    Which seems to be working, but isn't very effective from a requesting-time perspektive.

    EDIT: I could not use this implementation so i looked for an alternative library. I found out that the implementation of HttpUrlConnection uses OkHttp since Android 4.4. As OkHttp is opensource i could search if they have also problems with silent retries. And yep they had problems with it and fixed it in April, 2016. CommonsWare (a real android expert) explains that every manufacturer can decide which implementation they can use. As a consequence of this there must be a lot of devices out there that do silent retries on POST requests and as a developer we only can try some workarrounds.

    My solution will be to change the library

    EDIT 2: To give you a final answer: You can now use OkHttp as the transport layer for Volley with minimal code.

    Another helpful solution

    0 讨论(0)
  • 2020-12-24 00:18

    Well, lot of time passed so I figured I will answer with my current (not perfect) solution for other people to easily see it (also written inside the question).

    Just set the readTimeout to 0 (no timeout) or at least the connection timeout value. This will make sure connection timeout will be raised before the read timeout.

    int timeoutMs = request.getTimeoutMs();    //  or whatever
    connection.setConnectTimeout(timeoutMs);   //  actual timeout desired
    connection.setReadTimeout(timeoutMs);      //  >= timeoutMs or 0
    

    Of course, it depends on the use of the request. Most of the times, the app is part of a project containing the related server, and you know read timeouts shouldn't happen anyway..

    As said, not really a "solution", but a very nice and 90% useful fix.

    0 讨论(0)
提交回复
热议问题