Skip to content

Network on Main Thread #3145

@DavidEdwards

Description

@DavidEdwards

The issue

My issue is extremely intermittent. It does not appear every time. Infact, only quite rarely. Perhaps a couple of times per week.

In the first step, you see that I am directly starting a new Thread for running my blocking function in.

In the last step, I even check that the Thread is not running on the Main Thread.

Could okhttp be pushing the request onto the Main Thread?

My Exception

01-31 09:29:58.459 15392-15814/dae.evepi E/UncaughtException: android.os.NetworkOnMainThreadException
	  at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303)
	  at com.android.org.conscrypt.Platform.blockGuardOnNetwork(Platform.java:300)
	  at com.android.org.conscrypt.OpenSSLSocketImpl$SSLOutputStream.write(OpenSSLSocketImpl.java:808)
	  at okio.Okio$1.write(SourceFile:78)
	  at okio.AsyncTimeout$1.write(SourceFile:179)
	  at okio.RealBufferedSink.flush(SourceFile:216)
	  at okhttp3.internal.http2.Http2Writer.flush(SourceFile:121)
	  at okhttp3.internal.http2.Http2Connection.newStream(SourceFile:239)
	  at okhttp3.internal.http2.Http2Connection.newStream(SourceFile:205)
	  at okhttp3.internal.http2.Http2Codec.writeRequestHeaders(SourceFile:105)
	  at okhttp3.internal.http.CallServerInterceptor.intercept(SourceFile:43)
	  at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:92)
	  at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:67)
	  at dae.evepi.network.LoggingInterceptor.intercept(SourceFile:20) /* duplicate of your LoggingInterceptor recipe */
	  at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:92)
	  at okhttp3.internal.connection.ConnectInterceptor.intercept(SourceFile:45)
	  at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:92)
	  at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:67)
	  at okhttp3.internal.cache.CacheInterceptor.intercept(SourceFile:93)
	  at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:92)
	  at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:67)
	  at okhttp3.internal.http.BridgeInterceptor.intercept(SourceFile:93)
	  at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:92)
	  at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(SourceFile:120)
	  at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:92)
	  at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:67)
	  at okhttp3.RealCall.b(SourceFile:179)
	  at okhttp3.RealCall.execute(SourceFile:63)
	  at dae.evepi.network.Api.a(SourceFile:188)
	  at dae.evepi.network.Api.getPlanetLayoutBlocking(SourceFile:713)
	  at dae.evepi.network.Api$7.run(SourceFile:753)
	  at java.lang.Thread.run(Thread.java:761)

My code

	// at dae.evepi.network.Api$7.run(SourceFile:753)
    public void getPlanetLayout(@NonNull final Character c, @NonNull final Planet p, @NonNull final PinCallback callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                getPlanetLayoutBlocking(c, p, callback);
            }
        }).start();
    }
	// at dae.evepi.network.Api.getPlanetLayoutBlocking(SourceFile:713)
    @WorkerThread
    @Nullable
    public List<Pin> getPlanetLayoutBlocking(@NonNull final Character c, @NonNull final Planet p, @NonNull final PinCallback callback) {
        final String CACHE_KEY = "Api.getPlanetLayout(Character="+c.getId()+",Planet="+p.getId()+",PinCallback)";
        if(isCached(CACHE_KEY)) {
            LogUtils.log("W::Planet pins are cached. Don't refresh.");
            EventBus.getDefault().post(new EsiCacheEvent(getCacheExpireTime(CACHE_KEY)));
            return null;
        }

        Response response = null;

        try {
            Request request = new Request.Builder()
                    .url(String.format(Locale.US, AN_API_CALL, c.getId(), p.getId()))
                    .header("User-Agent", USER_AGENT)
                    .header("Authorization", "...")
                    .header("Host", "...")
                    .build();
            response = retryWithBackoff(request);

            if(response != null && response.code() == 200) {
                // Some stuff
            } else {
                // Some other stuff
            }
        } catch (MalformedURLException e) {
            LogUtils.log("E::e: "+e);
            e.printStackTrace();
            callback.onError(response, e);
        } catch (IOException e) {
            LogUtils.log("E::e: "+e);
            e.printStackTrace();
            callback.onError(response, e);
        } catch (JSONException e) {
            LogUtils.log("E::e: "+e);
            e.printStackTrace();
            callback.onError(response, e);
        }
        return null;
    }
	// at dae.evepi.network.Api.a(SourceFile:188)
    @WorkerThread
    @Nullable
    private Response retryWithBackoff(@NonNull Request request) throws IOException {
        Response response = null;

        int retryAttempt = 0;
        int backoffTime = 500;

        while(++retryAttempt <= MAX_RETRIES) {
            if(retryAttempt > 1) {
                LogUtils.log("W::There was an error accessing the API. We will try again in "+backoffTime+"ms");
                Utils.sleep(backoffTime); /* just a wrapped Thread.sleep(...); */
                backoffTime *= RETRY_DEPLAY_MULTIPLIER;
            }

            try {
                // This if block is never entered
                if(Looper.myLooper() == Looper.getMainLooper()) {
                    LogUtils.log("CRIT", "WTF::Attempting to call '"+request.url().toString()+"' on the main thread ("+retryAttempt+"/"+MAX_RETRIES+").");
                    LogUtils.logCaller("Trace critical error of network on main thread.");
                }

                response = mClient.newCall(request).execute();

                if (response.code() == 200) {
                    break;
                }
            } catch (SocketTimeoutException e) {
                LogUtils.log("E::Socket request timed out for '"+request.url().toString()+"'");
            }
        }

        return response;
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions