I'm successfully uploading smaller files < 10MB via okhttp (3.8.1) via https.
- Testet on different Android 6 and 7 devices.
- buildtools 27.0.0
- compiledSDK 27
Using following libraries:
- com.squareup.okhttp3:okhttp:3.8.1
- com.squareup.okhttp3:logging-interceptor:3.8.1
- com.squareup.okhttp3:okhttp-urlconnection:3.8.1
But if I try the same code with a file around 100-200MB the upload fails with the Exception:
javax.net.ssl.SSLException: Write error: ssl=0x559a6311d0: I/O error during system call, Connection reset by peer
at com.android.org.conscrypt.NativeCrypto.SSL_write(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl$SSLOutputStream.write(OpenSSLSocketImpl.java:771)
at okio.Okio$1.write(Okio.java:79)
at okio.AsyncTimeout$1.write(AsyncTimeout.java:180)
at okio.RealBufferedSink.emitCompleteSegments(RealBufferedSink.java:171)
at okio.RealBufferedSink.write(RealBufferedSink.java:41)
at okhttp3.internal.http1.Http1Codec$ChunkedSink.write(Http1Codec.java:325)
at okio.RealBufferedSink.emitCompleteSegments(RealBufferedSink.java:171)
at okio.RealBufferedSink.write(RealBufferedSink.java:91)
at de.fhdo.gobsis.mobile.libraries.ProgressRequestBody.writeTo(ProgressRequestBody.java:73)
at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:62)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:120)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:185)
at okhttp3.RealCall.execute(RealCall.java:69)
at com.example.services.Uploadervice.onHandleIntent(UploadCaseService.java:274)
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)
The device is running and app in foreground. I'm using the following code in an Android IntentService:
ProgressRequestBody body = new ProgressRequestBody(
getApplicationContext(),
new ProgressRequestBody.UploadInfo(Uri.fromFile(json), json.length()),
new ProgressRequestBody.ProgressCallback() {
@Override
public void onProgress(long progress, long total) {
publishProgress(progress, total);
}
});
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.MINUTES)
.writeTimeout(10, TimeUnit.MINUTES)
.readTimeout(10, TimeUnit.MINUTES)
.build();
Request request = new Request.Builder()
.header("X-Client-Type", "Android")
.addHeader("APIKEY", "SomeRND")
.url(url)
.post(body)
.build();
//Exception occures here:
Response response = client.newCall(request).execute();
The ProgressRequestBody extends the default okhttp RequestBody adds an interface for reporting the current uploadprogress. I overwrote the writeTo(BufferedSink sink)-Method like this:
@Override
public void writeTo(BufferedSink sink) throws IOException {
long fileLength = mUploadInfo.contentLength;
byte[] buffer = new byte[65536];
InputStream in = in();
long uploaded = 0;
try {
int read;
while((read = in.read(buffer)) != -1) {
mListener.onProgress(uploaded, fileLength);
uploaded += read;
sink.write(buffer, 0, read);
}
} finally {
in.close();
}
}
The file is read via the in()-method
private InputStream in() throws IOException {
InputStream stream = null;
try {
stream = getContentResolver().openInputStream(mUploadInfo.contentUri);
} catch (Exception ex) {
Log.e(LOG_TAG, "Error getting input stream for upload", ex);
}
return stream;
}
The upload failes after ~3-5 minutes. Can someone tell me how I can get a stable connection or resume it after its broken? In several posts I read that ssl exception occurences are not rare on large file uploads but I found no satisfying solution on how to fix this.