I\'ve started getting a
DEBUG/skia(xxxx): --- decoder->decode returned false
issue on a few profile images from Facebook that I use in
Here is what the issue was for me:
From the emulator I would save the jpg file locally (on the emulated sdcard) and then attempt to read it up and display it using decode on the emulator and it worked. Then, as a test, I copied the file (using adb pull) to my development (xp) machine and it would display using 'paint'. Then, from the emulator, I uploaded the file (via http post) to my win2003 server. Using 'paint' it displayed there as well. But when I downloaded it back to the emulator (via http get), it failed during the decode.
Then I noticed that the file uploaded to the win2003 server was two bytes smaller than the original. Not totally sure how that happened because I've been using the same upload logic for years and never noticed the issue before. As a test, I simply appended two more random bytes during the upload so the file size was exactly the same. Then, when downloaded back to the emulator, it decoded and displayed properly.
Just as a check, I appended two random bytes over on my xcode projects and then those jpg files also displayed on the android emulator as well.
So, although the files which were two bytes smaller displayed everywhere else, they would not on the emulator. Apparently decode is doing some sort of CRC before it attemps to decode and decides it cannot continue. And hence the error.
The source code from this ImageDownloader.java is a good orientation. It has a bug fix which addresses the Issue 6066 by providing a patched FlushedInputStream
class.
Another thing which you might want to take care of, is to execute the decoding in the same thread as the HTTP request was executed:
@Override
protected Bitmap doInBackground(String... url) {
// execute HTTP GET request and decode response
...
return bitmap
}
@Override
protected void onPostExecute(Bitmap result) {
imageView.setImageBitmap(result);
}
I had done the decoding in the onPostExecute()
, which is executed in the UI thread, and it would not work anymore, giving me the same error.
Here is a way that worked for me:
public static Bitmap loadImageFromUrl(String url) {
URL m;
InputStream i = null;
BufferedInputStream bis = null;
ByteArrayOutputStream out =null;
try {
m = new URL(url);
i = (InputStream) m.getContent();
bis = new BufferedInputStream(i,1024 * 8);
out = new ByteArrayOutputStream();
int len=0;
byte[] buffer = new byte[1024];
while((len = bis.read(buffer)) != -1){
out.write(buffer, 0, len);
}
out.close();
bis.close();
} catch (MalformedURLException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
byte[] data = out.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
//Drawable d = Drawable.createFromStream(i, "src");
return bitmap;
}
I loaded the image by multithreading, and then I had to loop reading the inputStream when the thread's time was held by another. Make sure the inputStream is read fully.
There is a bug in FlushedInputStream(is). it fails on slow connections but you can try my magical code to fix it.
Bitmap b = BitmapFactory.decodeStream(new FlushedInputStream(is));
imageView.setImageBitmap(b);
create a static class outside your method
static class FlushedInputStream extends FilterInputStream {
public FlushedInputStream(InputStream inputStream) {
super(inputStream);
}
@Override
public long skip(long n) throws IOException {
long totalBytesSkipped = 0L;
while (totalBytesSkipped < n) {
long bytesSkipped = in.skip(n - totalBytesSkipped);
if (bytesSkipped == 0L) {
int b = read();
if (b < 0) {
break; // we reached EOF
} else {
bytesSkipped = 1; // we read one byte
}
}
totalBytesSkipped += bytesSkipped;
}
return totalBytesSkipped;
}
}
and here you go.. now you will not have any problem.
I ran into this issue as well using Xamarin. To fix it I simply used the Universal Image Loader Xamarin Component and it worked like a charm.
Hope this helps!
Here is a way that worked for me:
HttpGet httpRequest = new HttpGet(url);
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = (HttpResponse) httpclient
.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufferedHttpEntity = new BufferedHttpEntity(entity);
InputStream is = bufferedHttpEntity.getContent();
Drawable d = Drawable.createFromStream(is, "");
//or bitmap
//Bitmap b = BitmapFactory.decodeStream(is);