Android-декодер-> декодирование возвращено false для Bitmap download
Я начал получать
DEBUG/skia(xxxx): --- decoder->decode returned false
выведите несколько изображений профиля из Facebook, которые я использую в ImageViews. Большинство работает отлично, но время от времени я обнаруживаю тот, который никогда не работает.
Я компилирую свое приложение против Android 1.6 для обеспечения обратной совместимости.
Я немного поработал и обнаружил несколько потоков в этом вопросе. Я уже использую FlushedInputStream, обсуждаемый здесь: http://code.google.com/p/android/issues/detail?id=6066
Bitmap b = BitmapFactory.decodeStream(new FlushedInputStream(is));
imageView.setImageBitmap(b);
Вот пример, который вызывает у меня проблемы:
http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs269.snc3/23132_639284607_390_q.jpg
Может кто-нибудь проверить изображение и помочь мне выяснить, что вызывает проблемы?
Ответы
Ответ 1
В FlushedInputStream (есть) есть ошибка. он не работает при медленных соединениях, но вы можете попробовать мой магический код, чтобы исправить его.
Bitmap b = BitmapFactory.decodeStream(new FlushedInputStream(is));
imageView.setImageBitmap(b);
создать статический класс вне вашего метода
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;
}
}
и здесь вы идете.. теперь у вас не будет проблем.
Ответ 2
Вот как это работает для меня:
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);
Ответ 3
Исходный код этого ImageDownloader.java является хорошей ориентацией. У этого есть исправление ошибки, которое адресовано Проблема 6066, предоставив исправленный класс FlushedInputStream
.
Еще одна вещь, которую вы, возможно, захотите позаботиться, - выполнить декодирование в том же потоке, что и HTTP-запрос:
@Override
protected Bitmap doInBackground(String... url) {
// execute HTTP GET request and decode response
...
return bitmap
}
@Override
protected void onPostExecute(Bitmap result) {
imageView.setImageBitmap(result);
}
Я выполнил декодирование в onPostExecute()
, которое выполняется в потоке пользовательского интерфейса, и оно больше не работает, что дает мне ту же ошибку.
Ответ 4
Вот как это работает для меня:
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;
}
Я загрузил изображение с помощью многопоточности, а затем мне пришлось зацикливать чтение входного потока, когда время потока удерживалось другим. Убедитесь, что входной поток прочитан полностью.
Ответ 5
Вот что было для меня проблемой:
Из эмулятора я бы сохранил файл jpg локально (на эмулированной SD-карте), а затем попытался его прочитать и отобразить с помощью декодирования на эмуляторе, и он сработал. Затем, в качестве теста, я скопировал файл (с помощью adb pull) на мою машину разработки (xp), и он отобразится с использованием "paint". Затем из эмулятора я загрузил файл (через http post) на мой сервер win2003. Используя "paint", он также отображается там. Но когда я загрузил его обратно в эмулятор (через http get), он потерпел неудачу во время декодирования.
Затем я заметил, что файл, загруженный на сервер win2003, был на два байта меньше оригинала. Не совсем уверен, как это произошло, потому что я использую одну и ту же логику загрузки в течение многих лет и никогда не замечал проблему раньше. В качестве теста я просто добавил еще два случайных байта во время загрузки, поэтому размер файла был точно таким же. Затем, при загрузке обратно в эмулятор, он декодируется и отображается правильно.
Так же, как проверка, я добавил два случайных байта в мои проекты xcode, а затем эти файлы jpg также отображались на эмуляторе Android.
Итак, хотя файлы, которые были на два байта меньше отображались везде, они не были бы на эмуляторе. По-видимому, декодирование делает какой-то CRC, прежде чем он попытается декодировать и решает, что он не может продолжаться. И, следовательно, ошибка.
Ответ 6
Другие, столкнувшиеся с проблемами в Android KitKat 4.4, будут полезны
Bitmap b = BitmapFactory.decodeStream(new BufferedInputStream(is));
imageView.setImageBitmap(b);
Я столкнулся с этой проблемой в серии Nexus. После обновления до 4.4.
Ответ 7
Я столкнулся с этой проблемой, используя Xamarin. Чтобы исправить это, я просто использовал Universal Image Loader Xamarin Component и работал как шарм.
Надеюсь, это поможет!