67

In my project I need to store an image into a sqlite database and also need to retrieve it to show in my android emulator. When I show it directly after decoding the encoded string, which I got from Java class using sockets, the image displays there. But when I store a byte array code of the string into the sqlite database with the datatype blob and then again retrieve it by using the getblob() function it contains a different value and this error occurs:

JAVA.lang.NULLPointerException: Factory returns null.

I need a suggestion to store a bitmap image into a sqlite database and also to retrieve it from the sqlite database.

Toon Krijthe
  • 52,876
  • 38
  • 145
  • 202
Rahul Gautam
  • 1,121
  • 3
  • 11
  • 18

2 Answers2

150

Setting Up the database

public class DatabaseHelper extends SQLiteOpenHelper {
    // Database Version
    private static final int DATABASE_VERSION = 1;

    // Database Name
    private static final String DATABASE_NAME = "database_name";

    // Table Names
    private static final String DB_TABLE = "table_image";

    // column names
    private static final String KEY_NAME = "image_name";
    private static final String KEY_IMAGE = "image_data";

    // Table create statement
    private static final String CREATE_TABLE_IMAGE = "CREATE TABLE " + DB_TABLE + "("+ 
                       KEY_NAME + " TEXT," + 
                       KEY_IMAGE + " BLOB);";

    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

        // creating table
        db.execSQL(CREATE_TABLE_IMAGE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // on upgrade drop older tables
        db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE);

        // create new table
        onCreate(db);
    }
}

Insert in the Database:

public void addEntry( String name, byte[] image) throws SQLiteException{
    SQLiteDatabase database = this.getWritableDatabase();
    ContentValues cv = new  ContentValues();
    cv.put(KEY_NAME,    name);
    cv.put(KEY_IMAGE,   image);
    database.insert( DB_TABLE, null, cv );
}

Retrieving data:

 byte[] image = cursor.getBlob(1);

Note:

  1. Before inserting into database, you need to convert your Bitmap image into byte array first then apply it using database query.
  2. When retrieving from database, you certainly have a byte array of image, what you need to do is to convert byte array back to original image. So, you have to make use of BitmapFactory to decode.

Below is an Utility class which I hope could help you:

public class DbBitmapUtility {

    // convert from bitmap to byte array
    public static byte[] getBytes(Bitmap bitmap) {
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(CompressFormat.PNG, 0, stream);
        return stream.toByteArray();
    }

    // convert from byte array to bitmap
    public static Bitmap getImage(byte[] image) {
        return BitmapFactory.decodeByteArray(image, 0, image.length);
    }
}


Further reading
If you are not familiar how to insert and retrieve into a database, go through this tutorial.

Lazy Ninja
  • 22,342
  • 9
  • 83
  • 103
  • 2
    @Lazy Ninja, add a quote(**"**) before **CREATE TABLE**, i'm not able to do this minor edit. – Abdul Saleem Sep 30 '15 at 07:03
  • 3
    @LazyNinja, I am using your answer to help me store and retreive bitmap images and strings. This post is so helpful! I had a question about how to "Insert into the Database". On the line "database.insert( DB_TABLE, null, cv );", how are you defining database? – Natalie May 13 '16 at 23:06
  • @Natalie use SQLiteDatabase database = this.getWritableDatabase(); I have added it in the source code. And I think the following link could be useful: http://mrbool.com/how-to-insert-data-into-a-sqlite-database-in-android/28895 – Lazy Ninja May 17 '16 at 03:48
  • Excellent answer bro :) Just one note: While retireving data byte[] image = cursor.getBlob(1); here "1" refers to the order/index of column in the database...note that the column "blob" is the second column, first-0 and second-1 ..Thus it would be much better if you create a contract class and do "byte[] image = cursor.getBlob(cursor.getColumnIndex(YourContractClass.YourEntry.COL_BLOB));" – Sumit Jha Dec 22 '16 at 09:23
8

If you are working with Android's MediaStore database, here is how to store an image and then display it after it is saved.

on button click write this

 Intent in = new Intent(Intent.ACTION_PICK,
                    android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            in.putExtra("crop", "true");
            in.putExtra("outputX", 100);
            in.putExtra("outputY", 100);
            in.putExtra("scale", true);
            in.putExtra("return-data", true);

            startActivityForResult(in, 1);

then do this in your activity

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // TODO Auto-generated method stub
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == 1 && resultCode == RESULT_OK && data != null) {

            Bitmap bmp = (Bitmap) data.getExtras().get("data");

            img.setImageBitmap(bmp);
            btnadd.requestFocus();

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            bmp.compress(Bitmap.CompressFormat.JPEG, 100, baos);
            byte[] b = baos.toByteArray();
            String encodedImageString = Base64.encodeToString(b, Base64.DEFAULT);

            byte[] bytarray = Base64.decode(encodedImageString, Base64.DEFAULT);
            Bitmap bmimage = BitmapFactory.decodeByteArray(bytarray, 0,
                    bytarray.length);

        }

    }
Abandoned Cart
  • 4,512
  • 1
  • 34
  • 41
Yash
  • 1,751
  • 13
  • 14