2010-08-20 14 views
5

Estoy almacenando en caché los archivos de imagen como una burbuja en una base de datos SQLite. Tengo una aplicación similar en otra plataforma que hace lo mismo con los mismos archivos de imagen. Las bases de datos en ambas plataformas informan el mismo tamaño exacto para las mismas imágenes. Así que creo, pero no puedo garantizar, que los datos de la imagen estén ingresando a la base de datos intactos.Problema al crear un Drawable desde una Blob de SQLite

Pero cuando intento crear un Drawable, la consola imprime "DEBUG/skia (267): --- decodificador-> decodificador devuelto falso".

Los pasos son:

  1. Leer la burbuja en una matriz de bytes.

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

    b = imageDataCursor.getBlob (1);

  2. Crea un InputStream desde la matriz de bytes.

    ByteArrayInputStream is = new ByteArrayInputStream (b);

  3. Cree un Drawable del InputStream. (esto es lo que crea el mensaje 'decodificador' anterior)

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

  4. Establezca ImageView.image en Drawable.

    imgView.setImageDrawable (drw);

Hasta ahora, no hay alegría. ¿Alguna sugerencia?

Respuesta

1

Voy a publicar mi solución para ayudar a cualquier persona con un problema similar.

He intentado probar la matriz de bytes que estoy leyendo de la base de datos escribiéndola en un archivo y luego viendo el archivo. Resulta que los datos de blobs en la base de datos no están completos: obtengo algunas líneas de la imagen, pero no toda la imagen.

La solución consistía en crear un BufferedInputStream y un ByteArrayBuffer para leer en la imagen desde el servidor remoto. El código para capturar un archivo de imagen desde un servidor remoto y crear una matriz de bytes a ser capaz de escribir a una base de datos SQLite es el siguiente:

   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

perseguí mi cola alrededor en este durante bastante tiempo. La respuesta de deSelby me ayudó. Aquí está mi código que descarga imágenes (PNG y JPG) desde Facebook, luego almacena/recupera los datos de una tabla sqlite usando la ruta como referencia.

Como puede ver, en realidad intenta leer la imagen de la tabla primero, si está allí simplemente la devuelve; de ​​lo contrario, la obtiene de Facebook, la almacena en la base de datos y luego la devuelve.

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

Mi writeImage se ve así (ver a continuación).

Images.IMAGE hace referencia al nombre de una columna BLOB en mi tabla. El punto principal aquí es que puedes escribir el byte [] directamente en la columna BLOB de la base de datos. Escribo la hora (utc) para poder borrar datos antiguos de acuerdo con las políticas de API de Facebook sobre datos de almacenamiento en caché.

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

} 

Puedo usar un proveedor de contenido para mi db, pero para los que no, el código de inserción se parece a esto, que se puede utilizar directamente en su base de datos sin un proveedor. (Solo para su información)

rowId = db.insert(IMAGES_TABLE, null, values); 
Cuestiones relacionadas