Android中的SocketTimeoutException超时

时间:2017-03-12 11:00:57

标签: android json http url

我是通过GET请求从网上获取JSON数据。代码如下,即使问题似乎是“概念性的”。

/**
 * Make an HTTP request to the given URL and return a String as the response.
 */
public static String makeHttpRequest(URL url) throws IOException {
    String jsonResponse = "";

    //Check that url is not null
    if(url == null){
        return jsonResponse;
    }

    HttpURLConnection urlConnection = null;
    InputStream inputStream = null;
    try {
        urlConnection = (HttpURLConnection) url.openConnection();
        urlConnection.setRequestMethod("GET");
      urlConnection.setReadTimeout(10000 /* milliseconds */);
           urlConnection.setConnectTimeout(15000 /* milliseconds */);
         urlConnection.connect();

        //If the request was successfull (code 200)
        //then read the imput string and parse the response
        if(urlConnection.getResponseCode() == 200) {
            inputStream = urlConnection.getInputStream();
            jsonResponse = readFromStream(inputStream);
        }
        else {
            Log.e(LOG_TAG_MAIN, "Error Response code" + urlConnection.getResponseCode());
        }

    } catch (IOException e) {
        Log.e(LOG_TAG_MAIN, "Problem the JSON results", e);
    } finally {
        if (urlConnection != null) {
            urlConnection.disconnect();
        }
        if (inputStream != null) {
            // Closing the input stream could throw an IOException, which is why
            // the makeHttpRequest(URL url) method signature specifies than an IOException
            // could be thrown.
            inputStream.close();
        }
    }
    return jsonResponse;
}
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
/**
 * Convert the {@link InputStream} into a String which contains the
 * whole JSON response from the server.
 */
public static String readFromStream(InputStream inputStream) throws IOException {
    StringBuilder output = new StringBuilder();
    if (inputStream != null) {
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
        BufferedReader reader = new BufferedReader(inputStreamReader);
        String line = reader.readLine();
        while (line != null) {
            output.append(line);
            line = reader.readLine();
        }
    }
    return output.toString();
}

确实以下代码工作了好几个月,但突然开始抛出:

E/com.example.android.abcfolio.MainActivity: Problem the JSON results
                                             java.net.SocketTimeoutException: timeout
 at com.android.okhttp.okio.Okio$3.newTimeoutException(Okio.java:207)
 at com.android.okhttp.okio.AsyncTimeout.exit(AsyncTimeout.java:250)
 at com.android.okhttp.okio.AsyncTimeout$2.read(AsyncTimeout.java:217)
 at com.android.okhttp.okio.RealBufferedSource.request(RealBufferedSource.java:71)
 at com.android.okhttp.okio.RealBufferedSource.require(RealBufferedSource.java:64)
 at com.android.okhttp.okio.RealBufferedSource.readHexadecimalUnsignedLong(RealBufferedSource.java:270)
 at com.android.okhttp.internal.http.HttpConnection$ChunkedSource.readChunkSize(HttpConnection.java:479)
 at com.android.okhttp.internal.http.HttpConnection$ChunkedSource.read(HttpConnection.java:460)
 at com.android.okhttp.okio.RealBufferedSource.read(RealBufferedSource.java:50)
 at com.android.okhttp.okio.RealBufferedSource.exhausted(RealBufferedSource.java:60)
 at com.android.okhttp.okio.InflaterSource.refill(InflaterSource.java:101)
 at com.android.okhttp.okio.InflaterSource.read(InflaterSource.java:62)
 at com.android.okhttp.okio.GzipSource.read(GzipSource.java:80)
 at com.android.okhttp.okio.RealBufferedSource$1.read(RealBufferedSource.java:349)
 at java.io.InputStreamReader.read(InputStreamReader.java:233)
 at java.io.BufferedReader.fillBuf(BufferedReader.java:145)
 at java.io.BufferedReader.readLine(BufferedReader.java:397)
 at com.example.android.abcfolio.utils.NetworkCommonUtils.readFromStream(NetworkCommonUtils.java:102)
 at com.example.android.abcfolio.utils.NetworkCommonUtils.makeHttpRequest(NetworkCommonUtils.java:68)
 at com.example.android.abcfolio.utils.NetworkCoinMarketCapUtils.fetchCoinMarketCapData(NetworkCoinMarketCapUtils.java:44)
 at com.example.android.abcfolio.sync.CoinsSyncTask.syncCoins(CoinsSyncTask.java:65)
 at com.example.android.abcfolio.sync.CoinsFirebaseJobService$1.doInBackground(CoinsFirebaseJobService.java:64)
 at com.example.android.abcfolio.sync.CoinsFirebaseJobService$1.doInBackground(CoinsFirebaseJobService.java:53)
 at android.os.AsyncTask$2.call(AsyncTask.java:295)
 at java.util.concurrent.FutureTask.run(FutureTask.java:237)
 at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
 at java.lang.Thread.run(Thread.java:818)

因为,我从未接触过这段代码,但我只在代码的其他部分添加了其他功能,我不明白发生了什么。我试图提高超时时间,但错误实际上立即出现,所以增加时间似乎没用。 我排除这是由于请求的大小,因为即使我只要求所有JSON的子集,它仍然会抱怨。

问题可能出在我正在查询的网站上吗?也许他们目前有太多要求?也许我用于开发的手机被禁止了太多的请求?

使用其他信息进行编辑: 1)问题是间歇性的。有时应用程序工作正常,所有数据都正确加载。 2)有时这些消息显示在LogCat中,我不确定是否相关(特别是fmradio.jar):

03-12 12:49:36.600 16457-16457/? W/System: ClassLoader referenced unknown path: /data/app/com.example.android.abcfolio-2/lib/arm64
03-12 12:49:36.603 16457-16457/? I/InstantRun: Instant Run Runtime started. Android package is com.example.android.abcfolio, real application class is null.

                                               [ 03-12 12:49:36.607 16457:16457 W/         ]
                                               Unable to open '/system/framework/qcom.fmradio.jar': No such file or directory
03-12 12:49:36.607 16457-16457/? W/art: Failed to open zip archive '/system/framework/qcom.fmradio.jar': I/O Error

                                        [ 03-12 12:49:36.607 16457:16457 W/         ]
                                        Unable to open '/system/framework/oem-services.jar': No such file or directory
03-12 12:49:36.607 16457-16457/? W/art: Failed to open zip archive '/system/framework/oem-services.jar': I/O Error
03-12 12:49:37.149 16457-16470/? I/art: Debugger is no longer active
03-12 12:49:39.030 16457-16457/com.example.android.abcfolio W/System: ClassLoader referenced unknown path: /data/app/com.example.android.abcfolio-2/lib/arm64
03-12 12:49:43.962 16457-16457/com.example.android.abcfolio W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable

3)还有其他多个警告,如

W/PathParser: Points are too far apart 4.000000000000003 

这些应归功于ConstraintLayout。它可能是使用太多内存来在主线程上执行图形工作,这会在http请求中变成错误吗? (我似乎不太可能,但它可以解释为什么现在这个问题出现了,在我用ConstraintLayout插入了许多视图之后)

编辑2: 4)在应用程序中,我以两种不同的方式获取数据:一个使用简单的Loader扩展AsyncTaskLoader,另一个使用Firebase作业服务。是第二个给出问题的,即使它们获取相同的API并使用上面写的两种方法。

编辑3: 5)我现在确定问题不是由于最近在代码中所做的更改,因为即使是较旧的应用程序备份版本也会以相同的方式运行。 6)现在它扔了这个:

Problem parsing the JSON results
                                             java.io.EOFException
                                                 at com.android.okhttp.okio.RealBufferedSource.require(RealBufferedSource.java:64)
                                                 at com.android.okhttp.okio.RealBufferedSource.readHexadecimalUnsignedLong(RealBufferedSource.java:270)
                                                 at com.android.okhttp.internal.http.HttpConnection$ChunkedSource.readChunkSize(HttpConnection.java:479)
                                                 at com.android.okhttp.internal.http.HttpConnection$ChunkedSource.read(HttpConnection.java:460)
                                                 at com.android.okhttp.okio.RealBufferedSource.read(RealBufferedSource.java:50)
                                                 at com.android.okhttp.okio.RealBufferedSource.exhausted(RealBufferedSource.java:60)
                                                 at com.android.okhttp.okio.InflaterSource.refill(InflaterSource.java:101)
                                                 at com.android.okhttp.okio.InflaterSource.read(InflaterSource.java:62)
                                                 at com.android.okhttp.okio.GzipSource.read(GzipSource.java:80)
                                                 at com.android.okhttp.okio.RealBufferedSource$1.read(RealBufferedSource.java:349)
                                                 at java.io.InputStreamReader.read(InputStreamReader.java:233)
                                                 at java.io.BufferedReader.fillBuf(BufferedReader.java:145)
                                                 at java.io.BufferedReader.readLine(BufferedReader.java:397)
                                                 at com.example.android.abcfolio.utils.NetworkCommonUtils.readFromStream(NetworkCommonUtils.java:106)
                                                 at com.example.android.abcfolio.utils.NetworkCommonUtils.makeHttpRequest(NetworkCommonUtils.java:72)
                                                 at com.example.android.abcfolio.utils.NetworkCoinMarketCapUtils.fetchCoinMarketCapData(NetworkCoinMarketCapUtils.java:44)
                                                 at com.example.android.abcfolio.sync.CoinsSyncTask.syncCoins(CoinsSyncTask.java:89)
                                                 at com.example.android.abcfolio.sync.CoinsSyncIntentService.onHandleIntent(CoinsSyncIntentService.java:33)
                                                 at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:66)
                                                 at android.os.Handler.dispatchMessage(Handler.java:102)
                                                 at android.os.Looper.loop(Looper.java:148)
                                                 at android.os.HandlerThread.run(HandlerThread.java:61)

编辑4: 6)我已经记录了urlConnection.getResponseCode()+ urlConnection.getResponseMessage(),有时候,它会返回:504Gateway Time-out,而不是成功代码200。

1 个答案:

答案 0 :(得分:0)

当您设置超时时,服务器为您的请求提供的服务时间比您原先预期的要长。它们很短。它们应该在几分钟内,而不是几秒钟。

它与你的应用程序正在做的其他事情没有任何关系。