web-dev-qa-db-ja.com

OkHttp3 SocketTimeoutException(in Android app)-非同期リクエストの読み取りタイムアウトを設定するにはどうすればよいですか?

OkHttp3非同期Getを試行すると、Java.net.SocketTimeoutExceptionが発生し続けます。これは、読み取りタイムアウト値を十分に高く設定していないことを示しています(デフォルトは10秒だと思います)。

より大きな質問は「この例外を防ぐ方法」です。しかし、誰かがより良い初期戦略を持っていない限り、私の当面の質問は、「リクエストの読み取りタイムアウト値を設定する方法」です。

私のコードでは、Okttpレシピページの情報を使用しました ここ

Try-catchの最初の2行がコメントアウトされていることに注意してください。これは、ヘッダー情報(Request.Builder)を追加するために必要な種類のビルダー(タイムアウト値を設定できるビルダー、OkHttpClient.Builder)を使用できないためです。

私のコードは次のようになります:

    m_client = new OkHttpClient();


    try
    {
        //OkHttpClient.Builder bldr = m_client.newBuilder();
        //bldr.readTimeout(0, TimeUnit.SECONDS);

        Request.Builder reqBuilder = new Request.Builder();

        reqBuilder.addHeader("authorization", getToken());

        Request request = reqBuilder.url("http://plusdev.kooklah.com/api/v2_1/items/get").build();

        m_client.newCall(request).enqueue(new Callback()
        {
            @Override
            public void onFailure(Call call, IOException e)
            {
                Log.i("Logit", "Inside onFailure() -- IOException: " + e.getMessage() + " ----- stack trace: " + UtilGen.exceptionToString(e));

                runOnUiThread(new Runnable()
                {
                    @Override
                    public void run()
                    {
                       // do stuff on UI thread
                    }
                });
            }

            @Override
            public void onResponse(Call call, final Response responseIn)
            {
                try
                {
                    m_sServerResponse = responseIn.body().string();
                }
                catch (Exception ex)
                {
                    Log.i("LogIt", "          ---Inside onResponse() -- Exception occurred. ex: " + ex.toString());
                }

                runOnUiThread(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        Log.i("LogIt", "          ---Inside onResponse() -- inside run().");
                        if (!m_sServerResponse.isEmpty())
                        {
                            Log.i("LogIt", "          ---Inside onResponse() -- inside run() -- Success");
                            processDownloadedAssessments(m_sServerResponse);
                        }
                    }
                });
            }
        });
    }
    catch (Exception ex)
    {
        Log.i("LogIt", "ex: " + ex.getMessage());
    }

Okhttp githubサイトで、直接関連していると思われる報告された問題 here を見つけました。レシピページで説明されているように、その種のビルダーを非同期リクエストに耐えさせる方法がわからないため、前述のようにコメントアウトされている読み取りタイムアウトを設定することも推奨されています。

私の例外のスタックトレースは以下のとおりですが、ほとんどの場合、例外が発生しないことに注意してください。スタックトレース:

01-19 14:04:52.192: I/LogIt(25650): Inside onFailure() -- IOException: null ----- stack trace: Java.net.SocketTimeoutException
01-19 14:04:52.192: I/LogIt(25650):     at Java.net.PlainSocketImpl.read(PlainSocketImpl.Java:488)
01-19 14:04:52.192: I/LogIt(25650):     at Java.net.PlainSocketImpl.access$000(PlainSocketImpl.Java:37)
01-19 14:04:52.192: I/LogIt(25650):     at Java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.Java:237)
01-19 14:04:52.192: I/LogIt(25650):     at okio.Okio$2.read(Okio.Java:138)
01-19 14:04:52.192: I/LogIt(25650):     at okio.AsyncTimeout$2.read(AsyncTimeout.Java:236)
01-19 14:04:52.192: I/LogIt(25650):     at okio.RealBufferedSource.indexOf(RealBufferedSource.Java:325)
01-19 14:04:52.192: I/LogIt(25650):     at okio.RealBufferedSource.indexOf(RealBufferedSource.Java:314)
01-19 14:04:52.192: I/LogIt(25650):     at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.Java:210)
01-19 14:04:52.192: I/LogIt(25650):     at okhttp3.internal.http1.Http1Codec.readResponse(Http1Codec.Java:191)
01-19 14:04:52.192: I/LogIt(25650):     at okhttp3.internal.http1.Http1Codec.readResponseHeaders(Http1Codec.Java:132)
01-19 14:04:52.192: I/LogIt(25650):     at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.Java:54)
01-19 14:04:52.192: I/LogIt(25650):     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.Java:92)
01-19 14:04:52.192: I/LogIt(25650):     at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.Java:45)
01-19 14:04:52.192: I/LogIt(25650):     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.Java:92)
01-19 14:04:52.192: I/LogIt(25650):     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.Java:67)
01-19 14:04:52.192: I/LogIt(25650):     at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.Java:93)
01-19 14:04:52.192: I/LogIt(25650):     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.Java:92)
01-19 14:04:52.192: I/LogIt(25650):     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.Java:67)
01-19 14:04:52.192: I/LogIt(25650):     at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.Java:93)
01-19 14:04:52.192: I/LogIt(25650):     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.Java:92)
01-19 14:04:52.192: I/LogIt(25650):     at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.Java:120)
01-19 14:04:52.192: I/LogIt(25650):     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.Java:92)
01-19 14:04:52.192: I/LogIt(25650):     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.Java:67)
01-19 14:04:52.192: I/LogIt(25650):     at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.Java:179)
01-19 14:04:52.192: I/LogIt(25650):     at okhttp3.RealCall$AsyncCall.execute(RealCall.Java:129)
01-19 14:04:52.192: I/LogIt(25650):     at okhttp3.internal.NamedRunnable.run(NamedRunnable.Java:32)
01-19 14:04:52.192: I/LogIt(25650):     at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1112)
01-19 14:04:52.192: I/LogIt(25650):     at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:587)
01-19 14:04:52.192: I/LogIt(25650):     at Java.lang.Thread.run(Thread.Java:818)
6
Alyoshak

の代わりに

_m_client = new OkHttpClient();
_

次のようなビルダーを使用してクライアントを作成する必要があります。

_m_client = new OkHttpClient.Builder()
        .connectTimeout(10, TimeUnit.SECONDS)
        .writeTimeout(10, TimeUnit.SECONDS)
        .readTimeout(30, TimeUnit.SECONDS)
        .build();
_

このようなクライアントを作成すると、このクライアントで実行される各Requestm_client.newCall(...)を使用)は、ビルダーで指定されたタイムアウトを使用します。

17
LordRaydenMK