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;
}
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
My code