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.
01.
/**
02.
* The class that will provide the correct implementation of the skip method
03.
* this class extends the FilterInputStream
04.
*
05.
* @author Deep Shah
06.
*
07.
* @see <a href="http://www.gitshah.com/2011/05/fixing-skia-decoder-decode-returned.html">http://www.gitshah.com/2011/05/fixing-skia-decoder-decode-returned.html<;/a>
08.
* @see <a href="http://code.google.com/p/android/issues/detail?id=6066">http://code.google.com/p/android/issues/detail?id=6066<;/a>
09.
*/
10.
package
twig.nguyen.mustachify;
11.
12.
import
java.io.FilterInputStream;
13.
import
java.io.IOException;
14.
import
java.io.InputStream;
15.
16.
class
FlushedInputStream
extends
FilterInputStream {
17.
public
FlushedInputStream(
final
InputStream inputStream) {
18.
super
(inputStream);
19.
}
20.
21.
/**
22.
* Overriding the skip method to actually skip n bytes.
23.
* This implementation makes sure that we actually skip
24.
* the n bytes no matter what.
25.
*/
26.
@Override
27.
public
long
skip(
final
long
n)
throws
IOException {
28.
long
totalBytesSkipped = 0L;
29.
30.
while
(totalBytesSkipped < n) {
31.
long
bytesSkipped = in.skip(n - totalBytesSkipped);
32.
33.
if
(bytesSkipped == 0L) {
34.
int
bytesRead = read();
35.
36.
if
(bytesRead <
0
) {
// we reached EOF
37.
break
;
38.
}
39.
40.
bytesSkipped =
1
;
41.
}
42.
43.
totalBytesSkipped += bytesSkipped;
44.
}
45.
46.
return
totalBytesSkipped;
47.
}
48.
}
Believe it or not, that's the hard part done. All we gotta do now is use it.
1.
private
Bitmap loadBitmap(String url)
throws
MalformedURLException, IOException {
2.
return
BitmapFactory.decodeStream(
new
FlushedInputStream((InputStream)
new
URL(url).getContent()));
3.
}
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