2010-08-20 11 views
5

Ich speichere Bilddateien als Blob in einer SQLite-Datenbank. Ich habe eine ähnliche Anwendung auf einer anderen Plattform, die dasselbe mit den gleichen Bilddateien macht. Die Datenbanken auf beiden Plattformen geben genau die gleiche Größe für die gleichen Bilder an. Ich denke, kann aber nicht garantieren, dass die Bilddaten intakt in die Datenbank gelangen.Problem beim Erstellen eines Drawable aus einem SQLite-Blob

Aber wenn ich versuche, ein Drawable zu erstellen, druckt die Konsole "DEBUG/skia (267): --- Decoder-> Dekodierung falsch zurückgegeben".

Die Schritte sind:

  1. das Blob in ein Byte-Array gelesen.

    byte [] b = neues Byte [imageDataCursor.getInt (0)];

    b = imageDataCursor.getBlob (1);

  2. Erstellen Sie einen InputStream aus dem Byte-Array.

    ByteArrayInputStream ist = neues ByteArrayInputStream (b);

  3. Erstellen Sie eine Drawable aus dem InputStream. (Dies ist, was die "Decoder" Nachricht oben erzeugt)

    Drawable drw = Drawable.createFromStream (is, "articleImage");

  4. Setzen Sie ImageView.image auf Drawable.

    imgView.setImageDrawable (drw);

Bis jetzt keine Freude. Irgendwelche Vorschläge?

Antwort

1

Ich werde meine Lösung veröffentlichen, um jedem mit einem ähnlichen Problem zu helfen.

Ich habe versucht, das Byte-Array zu testen, das ich aus der Datenbank lese, indem ich es in eine Datei schreibe und dann die Datei anschaue. Es stellt sich heraus, dass die Blob-Daten in der Datenbank nicht vollständig sind - ich bekomme ein paar Zeilen des Bildes, aber nicht das gesamte Bild.

Die Lösung bestand darin, einen BufferedInputStream und einen ByteArrayBuffer zu erstellen, um das Image vom Remote-Server einzulesen. Der Code eine Bilddatei von einem entfernten Server zu erfassen und ein Byte-Array erstellen zu können, um es zu einer SQLite-Datenbank zu schreiben, sieht wie folgt aus:

   try { 
      HttpGet getMethod=new HttpGet(url); 
       HttpClient client=new DefaultHttpClient(); 
      HttpResponse response = client.execute(getMethod); 
      HttpEntity entity = response.getEntity(); 
      InputStream in = entity.getContent(); 
      BufferedInputStream bis = new BufferedInputStream(in); 
      ByteArrayBuffer baf = new ByteArrayBuffer(50); 
      int current = 0; 
      while ((current = bis.read()) != -1) { 
       baf.append((byte) current); 
      } 
      byte[] b = baf.toByteArray(); 
      database.updateArticleWithImageData(b, imageKey); 
     } 
     catch (Throwable t) { 
      android.util.Log.e("MyApp", "Exception fetching image file", t); 
     } 
0

Ich jagte meinen Schwanz um auf diese für eine ganze Weile. Die Antwort von deSelby hat mir geholfen. Hier ist mein Code, der Bilder (PNG und JPG) von Facebook herunterlädt und dann die Daten von einer sqlite-Tabelle unter Verwendung des Pfads als Referenz speichert/abruft.

Wie Sie sehen, versucht es tatsächlich zuerst das Bild aus der Tabelle zu lesen, wenn es dort ist, gibt es es einfach zurück, sonst holt es es von Facebook, speichert es in der Datenbank und gibt es dann zurück.

private static Drawable fetchPhoto(ContentResolver cr, int source, String path) { 
    Drawable image = null; 
    myDB mDb = myDB.getInstance(); 
    Cursor iCursor = mDb.fetchImage(cr, path); 
    if(iCursor != null && iCursor.moveToFirst()) {    
     byte[] bb = iCursor.getBlob(iCursor.getColumnIndex(Images.IMAGE)); 
     if(iCursor != null) iCursor.close(); 
     image = new BitmapDrawable(BitmapFactory.decodeByteArray(bb, 0, bb.length)); 
    } else { 
     if(iCursor != null) iCursor.close(); 
     //get image from path 
     try 
     { 
      InputStream is = (InputStream) new URL(path).getContent(); 
      BufferedInputStream bis = new BufferedInputStream(is); 
      ByteArrayBuffer baf = new ByteArrayBuffer(50); 
      int current = 0; 
      while ((current = bis.read()) != -1) { 
       baf.append((byte) current); 
      } 
      byte[] barray = baf.toByteArray(); 
      bis.close(); 
      is.close(); 
      /* write image to db */ 
      long id = mDb.writeImage(cr,source,path,barray); 
      image = new BitmapDrawable(BitmapFactory.decodeByteArray(barray, 0, barray.length));    
     }catch (Exception error) { 
      //System.out.println("Exc="+e); 
     } 
    } 
    return image; 
} 

Mein writeImage sieht so aus (siehe unten).

Images.IMAGE verweist auf den Namen einer BLOB-Spalte in meiner Tabelle. Der Hauptpunkt hier ist wirklich, dass Sie das Byte [] direkt in die Datenbank-BLOB-Spalte schreiben können. Ich schreibe die Zeit (utc), damit ich alte Daten in Übereinstimmung mit den Facebook API-Richtlinien zum Zwischenspeichern von Daten löschen kann.

public long writeImage(ContentResolver contentResolver, int source, String path, byte[] image) { 

    Time now = new Time(); 
    now.setToNow(); 
    ContentValues initialValues = new ContentValues();  
    initialValues.put(Images.IMAGE, image); 
    initialValues.put(Images.SOURCE, source); 
    initialValues.put(Images.PATH, path); 
    initialValues.put(Images.UTC, now.toMillis(false)); 
    if(source == 0) initialValues.put(Images.DIRTY, 1); // sync user created images 

    Uri newUri = contentResolver.insert(Images.CONTENT_URI, initialValues); 
    String Id = newUri.getPathSegments().get(1); 
    return Long.parseLong(Id); 

} 

Ich benutze einen Content-Provider für meine db, aber für diejenigen, die nicht der Einsatz Code sieht wie folgt aus, die Sie direkt in Ihre Datenbank ohne Provider nutzen können. (Nur zur Info).

rowId = db.insert(IMAGES_TABLE, null, values); 
Verwandte Themen