I was being driven insane this weird bug. The idea was simple enough.
- Open a stream to a HTTP URL.
- Use BitmapFactory to decode the stream.
- ...
- Profit.
Worked pretty well in the emulator! But for some reason on the actual test devices, it would fail every single time. Mind boggling!
After a few tests, I noticed something in the error logs.
decoder->decode returned false
The reason why the image fails to decode is because InputStream doesn't actually implement the skip() method.
This post pointed me in the right direction. Still unsure of how to implement it properly, it lead to Deep Shah's post. He had a perfectly solid implementation of FlushedInputStream that was well documented.
Below is a slightly cleaned up version with less documentation. If you need more information about how it works, see his post.
/**
* The class that will provide the correct implementation of the skip method
* this class extends the FilterInputStream
*
* @author Deep Shah
*
* @see http://www.gitshah.com/2011/05/fixing-skia-decoder-decode-returned.html
* @see http://code.google.com/p/android/issues/detail?id=6066
*/
package twig.nguyen.mustachify;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
class FlushedInputStream extends FilterInputStream {
public FlushedInputStream(final InputStream inputStream) {
super(inputStream);
}
/**
* Overriding the skip method to actually skip n bytes.
* This implementation makes sure that we actually skip
* the n bytes no matter what.
*/
@Override
public long skip(final long n) throws IOException {
long totalBytesSkipped = 0L;
while (totalBytesSkipped < n) {
long bytesSkipped = in.skip(n - totalBytesSkipped);
if (bytesSkipped == 0L) {
int bytesRead = read();
if (bytesRead < 0) { // we reached EOF
break;
}
bytesSkipped = 1;
}
totalBytesSkipped += bytesSkipped;
}
return totalBytesSkipped;
}
}
Believe it or not, that's the hard part done. All we gotta do now is use it.
private Bitmap loadBitmap(String url) throws MalformedURLException, IOException {
return BitmapFactory.decodeStream(new FlushedInputStream((InputStream) new URL(url).getContent()));
}
Whalla! With that Bitmap you can do whatever the heck you want with it.
Back to other pressing matters...
Source
- how to load an imageview by url in android?
- Android, Make an image at a URL equal to ImageView's image
- Android: Getting Drawable from URL not working for .jpg, only works for .png
- BitmapFactory.decodeStream() fails if InputStream.skip() does not skip fully
- Fixing the "skia decoder->decode returned false" error while downloading images on Android