2010-12-02 4 views
27

Ich habe angefangen, einAndroid Decoder-> zurück dekodieren false für Bitmap herunterladen

DEBUG/skia(xxxx): --- decoder->decode returned false 

Problem immer auf ein paar Profilbilder von Facebook, die ich in ImageViews verwenden. Die meisten funktionieren perfekt, aber ab und zu entdecke ich eine, die nie funktioniert.

Ich kompiliere meine Anwendung gegen Android 1.6 aus Gründen der Rückwärtskompatibilität.

Ich habe etwas graben und entdeckte eine Reihe von Threads auf das Problem. Ich verwende bereits die FlushedInputStream hier diskutiert: http://code.google.com/p/android/issues/detail?id=6066

Bitmap b = BitmapFactory.decodeStream(new FlushedInputStream(is)); 
imageView.setImageBitmap(b); 

Hier ist ein Beispiel, das mir Probleme verursacht: http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs269.snc3/23132_639284607_390_q.jpg

Kann jemand das Bild überprüfen und mir helfen, herauszufinden, was die Mühe verursacht?

+0

Internet saugt :-) – Nabin

Antwort

33

Es gibt einen Fehler in FlushedInputStream (is). es scheitert bei langsamen Verbindungen, aber Sie können versuchen, meinen magischen Code zu reparieren.

Bitmap b = BitmapFactory.decodeStream(new FlushedInputStream(is)); 
imageView.setImageBitmap(b); 

eine statische Klasse außerhalb Ihrer Methode

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; 
     } 
    } 

erstellen und hier gehen .. jetzt werden Sie keine Probleme haben.

+1

vergessen Sie nicht, mich zu wählen. : D cheers –

+0

Hallo Aizaz. Ich verwende bereits den FlushedInputStream. Es funktioniert nicht für das Bild in meiner Frage aufgelistet. – Richard

+0

Ich hatte ein ähnliches Problem mit b.recycle(); nach setting imageView's bitmap –

10

ist hier eine Weise, die für mich gearbeitet:

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); 
+0

arbeitete in meinem Fall auch, aber Gibt es jemand Erklärung zu diesem Problem? – marwinXXII

+0

Ich habe versucht, 5+ verschiedene Lösungen von SO, und keiner arbeitete für die größeren Bilder, mit denen ich Probleme hatte. Aber deine hat wie ein Zauber gearbeitet !!! Vielen Dank. – alfongj

+0

Cool! Das ist richtig :) @ marwinXXII: Der Schlüssel ist die Pufferung zu verwenden, um Verzögerungsprobleme beim Dekodieren zu vermeiden. Weitere Informationen: http://www.gitshah.com/2011/05/fixing-skia-decoder-decode-returned.html – caligari

2

Hier ist ein Weg, die für mich gearbeitet:

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; 
    } 

ich das Bild geladen von Multithreading und dann musste ich Schleife Lesung der inputStream, wenn die Zeit des Threads von einem anderen gehalten wurde. Stellen Sie sicher, dass der InputStream vollständig gelesen wird. Hier

+0

Ich stehe vor dem gleichen Problem und habe versucht, Ihren Code, aber es funktioniert nicht für mich. Ich bekomme immer noch den gleichen Fehler. –

1

ist, was das Problem war für mich:

Vom Emulator ich lokal die jpg-Datei (auf dem emulierten sdcard) retten würde und dann versuchen, es zu lesen, und es dekodieren auf dem Emulator angezeigt werden und es hat funktioniert. Dann, als Test, kopierte ich die Datei (mit adb pull) auf meine Entwicklungsmaschine (xp) und es würde mit 'paint' angezeigt. Dann, vom Emulator, habe ich die Datei (via http-Post) auf meinen Win2003-Server hochgeladen. Mit 'paint' wurde es auch dort angezeigt. Aber als ich es zurück auf den Emulator heruntergeladen habe (via http get), ist es beim Dekodieren fehlgeschlagen.

Dann bemerkte ich, dass die Datei, die auf den Win2003-Server hochgeladen wurde, zwei Bytes kleiner als das Original war. Nicht ganz sicher, wie das passiert ist, weil ich seit Jahren dieselbe Upload-Logik verwende und das Problem nie zuvor bemerkt habe. Als Test fügte ich einfach zwei weitere zufällige Bytes während des Uploads an, so dass die Dateigröße genau gleich war. Nach dem Zurückladen in den Emulator wird die Datei korrekt decodiert und angezeigt.

Wie eine Überprüfung, habe ich zwei zufällige Bytes an meine xcode-Projekte angehängt und dann diese jpg-Dateien auch auf dem Android-Emulator angezeigt.

Also, obwohl die Dateien, die zwei Bytes kleiner waren überall anders angezeigt, würden sie nicht auf dem Emulator.Offenbar macht decode eine Art von CRC, bevor es versucht zu dekodieren und entscheidet, dass es nicht weitermachen kann. Und daher der Fehler.

5

Der Quellcode von diesem ImageDownloader.java ist eine gute Orientierung. Es hat einen Bugfix, der die Issue 6066 durch Bereitstellung einer gepatchten FlushedInputStream Klasse adressiert.

Eine andere Sache, die Sie kümmern möchten, die Decodierung im selben Thread ausgeführt werden soll, wie die HTTP-Anforderung ausgeführt wurde:

@Override 
protected Bitmap doInBackground(String... url) { 
    // execute HTTP GET request and decode response 
    ... 
    return bitmap 
} 


@Override 
protected void onPostExecute(Bitmap result) { 
    imageView.setImageBitmap(result); 
} 

ich die Decodierung in der onPostExecute() getan hatte, der ausgeführt wird, im UI-Thread, und es würde nicht mehr funktionieren, mir den gleichen Fehler geben.

1

Andere, die Probleme in Android KitKat 4.4, stehen folgende wären hilfreich

Bitmap b = BitmapFactory.decodeStream(new BufferedInputStream(is)); 
imageView.setImageBitmap(b); 

ich dieses Problem in Nexus-Serie 4.4 Nach dem Update zugewandt wurde.

+0

Es passiert mir beim Öffnen mehrerer Dateien. Scheint wie ein wenig Speicher für das Dateizugriffslimit. Öffnen sie aus der OBB-Datei. –

+0

Es könnte sein, haben Sie immer noch Probleme nach dem so? –

+0

Begann stattdessen mit Zip-Datei. Zu viele Fehler in Obb. –

Verwandte Themen