从SQLite Blob创建Drawable的问题

时间:2010-08-20 16:14:16

标签: android

我将图像文件缓存为SQLite数据库中的blob。我在另一个平台上有类似的应用程序,使用相同的图像文件执行相同的操作。两个平台上的数据库报告相同图像的大小完全相同。所以我认为,但不能保证图像数据完整地进入数据库。

但是当我尝试创建一个Drawable时,控制台打印出“DEBUG / skia(267):--- decoder-> decode返回false”。

步骤如下:

  1. 将blob读入字节数组。

    byte [] b =新字节[imageDataCursor.getInt(0)];

    b = imageDataCursor.getBlob(1);

  2. 从字节数组中创建一个InputStream。

    ByteArrayInputStream is = new ByteArrayInputStream(b);

  3. 从InputStream创建Drawable。 (这就是上面创建“解码器”消息的内容)

    Drawable drw = Drawable.createFromStream(is,“articleImage”);

  4. 将ImageView.image设置为Drawable。

    imgView.setImageDrawable(DRW);

  5. 到目前为止,没有快乐。有什么建议吗?

2 个答案:

答案 0 :(得分:1)

我会发布我的解决方案来帮助有类似问题的人。

我尝试通过将数据库写入文件然后查看文件来测试我正在从数据库中读取的字节数组。事实证明,数据库中的blob数据并不完整 - 我得到的是几行图像,但不是整个图像。

解决方案涉及创建BufferedInputStream和ByteArrayBuffer以从远程服务器读取映像。从远程服务器捕获映像文件并创建一个字节数组以便能够将其写入sqlite数据库的代码如下所示:

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

答案 1 :(得分:0)

我在这上面拖了很长时间。 deSelby的答案帮助了我。这是我从Facebook下载图像(PNG和JPG)的代码,然后使用路径作为参考来存储/检索sqlite表中的数据。

正如你所看到的,它实际上是首先尝试从表中读取图像,如果它在那里它只是返回它,否则它从Facebook获取它,将它存储在数据库中然后返回它。

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

我的writeImage看起来像这样(见下文)。

Images.IMAGE引用表格中BLOB列的名称。 这里的要点是你可以将byte []直接写入数据库BLOB列。 我写时间(utc)所以我可以根据关于缓存数据的Facebook api政策清除旧数据。

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

}

我为我的数据库使用了一个内容提供程序,但是对于那些不使用内容提供程序的人来说,插入代码看起来像这样,你可以直接在没有提供程序的情况下使用它。 (仅供参考)。

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