Reputation: 9324
I would like to load json with volley and download images using BufferedInputStream
. Since these requests are made to LAN ip adresses on the non encrypted http port, I enabled android:usesCleartextTraffic="true"
I get this error from Volley:
com.android.volley.ParseError: org.json.JSONException: Unterminated object at character 20 of {"data":{"foo":"bar"
I use BufferedInputStream
like this:
private boolean getFileFromUrl(String url, String path) {
try (BufferedInputStream in = new BufferedInputStream(new URL(url).openStream());
FileOutputStream fileOutputStream = new FileOutputStream(path)) {
byte dataBuffer[] = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
fileOutputStream.write(dataBuffer, 0, bytesRead);
}
fileOutputStream.close();
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
If I provide a Content-Length
parameter on the server, sometimes I get this error:
W/System.err: java.net.ProtocolException: unexpected end of stream
at com.android.okhttp.internal.http.Http1xStream$FixedLengthSource.read(Http1xStream.java:398)
at com.android.okhttp.okio.RealBufferedSource$1.read(RealBufferedSource.java:372)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:248)
W/System.err: at java.io.BufferedInputStream.read1(BufferedInputStream.java:288)
W/System.err: at java.io.BufferedInputStream.read(BufferedInputStream.java:347)
If I have no Content-Length
parameter, some of the files are still not fully loaded. No IOException
is thrown, but I get this error, if I try to read some of the images:
<Corrupt JPEG data: premature end of data segment> from output_message
These errors happen randomly. If I open these urls with my browser, it can load them perfectly. I have no idea how to debug it.
I tried my getFileFromUrl
with a https
url, and then everíthing worked fine. Unfortunately I am not able to use https in this project, only http.
Edit
I created an executor service with one thread and then submit the getFileFromUrl
calls in Runnable
instances, but I still get the errors:
Executors.newFixedThreadPool(1);
Upvotes: 1
Views: 191
Reputation: 5788
From your code you are just opening raw http
connection with OpenConnection
. However, I'm not sure it's right(and simple) way to load image. You can use any other library for Image loading, which would take care about content length and headers.
Glide
. Glide.with(context)
.asBitmap()
.load(url)
.into(new CustomTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
// do whatever you want with bitmap
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
}
});
public void write(String fileName, Bitmap bitmap) {
try (FileOutputStream out = new FileOutputStream(filename)) {
bmp.compress(Bitmap.CompressFormat.PNG, 100, out); // bmp is your Bitmap
instance
// PNG is a lossless format, the compression factor (100) is ignored
} catch (IOException e) {
e.printStackTrace();
}
}
Upvotes: 0
Reputation: 76807
As it seems, that API (or OkHttp client) truncates the response body for some reason.
Either the OkHttp client has a low read-timeout (this value could be raised) or the API does not respond in time (or as whole JSON response). When it always responds properly in a web-browser, it should indeed be a(n Android) client-side issue. One way to handle this might be to catch that ProtocolException
, delete the aborted download and then retry to download the file again.
But I'd assume that the Content-Length
header's value might simply be wrong.
I mean, this value would be calculated correctly, when NOT setting it manually.
The client may only act abnormal upon erroneous instructions received.
Content-Length
tells the client how large the receive-buffer has to be ...
and even if the response is not truncated, the client will reject the excess.
For example:
Content-Length: 20
...is what the API apparently reports.
{"data":{"foo":"bar"
Content-Length: 22
...is what the API should report.
{"data":{"foo":"bar"}}
Upvotes: 2