Error while trying to save and retrieve images to database in android

I am new to android and I have a bug in my application.

My application does the following:

1- User can choose to import images from camera or gallery.

2- All images are saved in the database and the user can see them all as a list for other activities.

While I click the menu icon to go to another action to see all images the application crashes and I get the following error in the log file:

11-06 15:16:17.199: E/AndroidRuntime(1789): FATAL EXCEPTION: main
11-06 15:16:17.199: E/AndroidRuntime(1789): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.demodbimage/com.example.demodbimage.ImagesList}: java.lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.

      

MainActivity.java

public class MainActivity extends ActionBarActivity {
    private static int FROM_CAMERA = 1;
    private static int FROM_GALLERY = 2;
    ImageView background;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        background = (ImageView)findViewById(R.id.imgBackground);
       DataBaseHandler db = new DataBaseHandler(this);
     db.deleteAllContact();



    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.activity_main_actions, menu);

        android.app.ActionBar actionBar = getActionBar();

        actionBar.setDisplayHomeAsUpEnabled(true);

        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;

        }
        else if(id == R.id.action_camera) {

            showOptions();

            return true;
        }
        else if(id == R.id.action_view_as_list) {

            Intent i = new Intent(MainActivity.this,ImagesList.class);
            startActivity(i);
            return true;
        }

        return super.onOptionsItemSelected(item);
    }



    public void showOptions(){
        final String[] items = {"Camera","Gallery"};

        final int[] icons = {R.drawable.ic_camera,R.drawable.ic_gallery};


        ListAdapter adapter = new ArrayAdapter<String>( this, R.layout.list_item, items) {

            ViewHolder holder;

            class ViewHolder {
                ImageView icon;
                TextView title;
            }

            public View getView(int position, View convertView, ViewGroup parent) {
                final LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);


                if (convertView == null) {
                    convertView = inflater.inflate(R.layout.list_item, null);

                    holder = new ViewHolder();
                    holder.icon = (ImageView) convertView .findViewById(R.id.icon);

                    holder.title = (TextView) convertView .findViewById(R.id.title);
                    convertView.setTag(holder);
                } else {
                    // view already defined, retrieve view holder
                    holder = (ViewHolder) convertView.getTag();
                }     

                holder.title.setText(items[position]);
                holder.icon.setImageResource(icons[position]);
                return convertView;
            }
        };


        AlertDialog.Builder builder = new AlertDialog.Builder(this);

        builder.setTitle("Choose photo from:");
        builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                if(which == 0){
                     Intent fromCamera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                     startActivityForResult(fromCamera, FROM_CAMERA);

                }
                else{
                    Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                    i.setType("image/*");
                    startActivityForResult(i, FROM_GALLERY);

                }



            }

        });

        builder.create();
        builder.show();
    }



    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data){
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == FROM_GALLERY && resultCode == RESULT_OK && null != data) {
                Uri selectedImage = data.getData();
                String[] filePathColumn = { MediaStore.Images.Media.DATA };
                Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);

                cursor.moveToFirst();
                int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                String picturePath = cursor.getString(columnIndex);
                cursor.close();

                background.setImageBitmap(BitmapFactory.decodeFile(picturePath));
                insertToDatabase(BitmapFactory.decodeFile(picturePath));
        }
        else{
            if(requestCode == FROM_CAMERA  && resultCode == RESULT_OK && null != data )
            {

                Bundle extras = data.getExtras();
                Bitmap photo = extras.getParcelable("data");
                background.setImageBitmap(photo);
                insertToDatabase(photo);

            }
        }
    }
    public  void insertToDatabase(Bitmap img){
            DataBaseHandler db = new DataBaseHandler(this);
            //db.deleteAllContact();
            // get image from drawable

            //Drawable i = background.getBackground();
            //Bitmap image = ((BitmapDrawable)i).getBitmap();
            //Bitmap image = BitmapFactory.decodeResource(getResources(),R.id.imgBackground);

            // convert bitmap to byte
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            img.compress(Bitmap.CompressFormat.JPEG, 100, stream);
            byte imageInByte[] = stream.toByteArray();

             //Inserting Contacts
            Log.d("Insert: ", "Inserting ..");
            db.addContact(new Contact("Image", imageInByte));

    }



}

      

DataBaseHandler.java

public class DataBaseHandler extends SQLiteOpenHelper{
    private static final int DATABASE_VERSION = 1;
    private static final String DATABASE_NAME = "imagedb";
    private static final String TABLE_CONTACTS = "contacts";

    private static final String KEY_ID = "id";
    private static final String KEY_NAME = "name";
    private static final String KEY_IMAGE = "image";

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


    @Override
    public void onCreate(SQLiteDatabase db) {
        String CREATE_CONTACTS_TABLE = "CREATE TABLE " + TABLE_CONTACTS + "("
                + KEY_ID + " INTEGER PRIMARY KEY," + KEY_NAME + " TEXT,"
                + KEY_IMAGE + " BLOB" + ")";
        db.execSQL(CREATE_CONTACTS_TABLE);
    }


    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // Drop older table if existed
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_CONTACTS);

        // Create tables again
        onCreate(db);
    }


    // Adding new contact
    public void addContact(Contact contact) {
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(KEY_NAME, contact._name); // Contact Name
        values.put(KEY_IMAGE, contact._image); // Contact Phone

        // Inserting Row
        db.insert(TABLE_CONTACTS, null, values);
        db.close(); // Closing database connection
    }



    // Getting single contact
    Contact getContact(int id) {
        SQLiteDatabase db = this.getReadableDatabase();

        Cursor cursor = db.query(TABLE_CONTACTS, new String[] { KEY_ID,
                KEY_NAME, KEY_IMAGE }, KEY_ID + "=?",
                new String[] { String.valueOf(id) }, null, null, null, null);
        if (cursor != null)
            cursor.moveToFirst();

        Contact contact = new Contact(Integer.parseInt(cursor.getString(0)),
                cursor.getString(1), cursor.getBlob(1));

        // return contact
        return contact;

    }


    // Getting All Contacts
    public List<Contact> getAllContacts() {
        List<Contact> contactList = new ArrayList<Contact>();
        // Select All Query
        String selectQuery = "SELECT * FROM contacts ORDER BY name";

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);
        // looping through all rows and adding to list
        if (cursor.moveToFirst()) {
            do {
                Contact contact = new Contact();
                contact.setID(Integer.parseInt(cursor.getString(0)));
                contact.setName(cursor.getString(1));
                contact.setImage(cursor.getBlob(2));
                // Adding contact to list
                contactList.add(contact);
            } while (cursor.moveToNext());
        }
        // close inserting data from database
        db.close();
        // return contact list
        return contactList;

    }

    // Updating single contact
    public int updateContact(Contact contact) {
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(KEY_NAME, contact.getName());
        values.put(KEY_IMAGE, contact.getImage());

        // updating row
        return db.update(TABLE_CONTACTS, values, KEY_ID + " = ?",
                new String[] { String.valueOf(contact.getID()) });

    }

    // Deleting single contact
    public void deleteContact(Contact contact) {
        SQLiteDatabase db = this.getWritableDatabase();
        db.delete(TABLE_CONTACTS, KEY_ID + " = ?",
                new String[] { String.valueOf(contact.getID()) });
        db.close();
    }


    public void deleteAllContact() {
        SQLiteDatabase db = this.getWritableDatabase();

        db.delete(TABLE_CONTACTS,null,null);
        db.close();
    }




    // Getting contacts Count
    public int getContactsCount() {
        String countQuery = "SELECT * FROM " + TABLE_CONTACTS;
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery(countQuery, null);
        cursor.close();

        // return count
        return cursor.getCount();
    }
}

      

ImagesList.java

public class ImagesList extends Activity{

    ArrayList<Contact> imageArry = new ArrayList<Contact>();
    ContactImageAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState){
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.image_list);
        ListView dataList = (ListView) findViewById(R.id.listView1);


        DataBaseHandler db = new DataBaseHandler(this);

        // Reading all contacts from database
        List<Contact> contacts = db.getAllContacts();

            for (Contact cn : contacts) {
                String log = "ID:" + cn.getID() + " Name: " + cn.getName()  + " ,Image: " + cn.getImage();

                // Writing Contacts to log
                Log.d("Result: ", log);
                //add contacts data in arrayList
                imageArry.add(cn);

            }

        adapter = new ContactImageAdapter(this,R.layout.layout_row,imageArry);
        dataList.setAdapter(adapter);

    }


}

      

image_list.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <ListView
        android:id="@+id/listView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>

</LinearLayout>

      

layout_row.xml layout for each row as a list

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginTop="10dp"
        android:paddingBottom="10dp"    
        android:src="@drawable/ic_gallery" />

    <TextView
        android:id="@+id/tvImageName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/imageView1"
        android:layout_marginBottom="18dp"
        android:layout_toRightOf="@+id/imageView1"
        android:text="The name of the image"
        android:textAppearance="?android:attr/textAppearanceMedium" />

</RelativeLayout>

      

I wasted a lot of time looking for a solution but couldn't find it.

Thank you for your advice !!!

Complete log file:

11-06 15:16:17.199: E/AndroidRuntime(1789): FATAL EXCEPTION: main
11-06 15:16:17.199: E/AndroidRuntime(1789): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.demodbimage/com.example.demodbimage.ImagesList}: java.lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.
11-06 15:16:17.199: E/AndroidRuntime(1789):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2351)
11-06 15:16:17.199: E/AndroidRuntime(1789):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2403)
11-06 15:16:17.199: E/AndroidRuntime(1789):     at android.app.ActivityThread.access$600(ActivityThread.java:165)
11-06 15:16:17.199: E/AndroidRuntime(1789):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1373)
11-06 15:16:17.199: E/AndroidRuntime(1789):     at android.os.Handler.dispatchMessage(Handler.java:107)
11-06 15:16:17.199: E/AndroidRuntime(1789):     at android.os.Looper.loop(Looper.java:194)
11-06 15:16:17.199: E/AndroidRuntime(1789):     at android.app.ActivityThread.main(ActivityThread.java:5391)
11-06 15:16:17.199: E/AndroidRuntime(1789):     at java.lang.reflect.Method.invokeNative(Native Method)
11-06 15:16:17.199: E/AndroidRuntime(1789):     at java.lang.reflect.Method.invoke(Method.java:525)
11-06 15:16:17.199: E/AndroidRuntime(1789):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
11-06 15:16:17.199: E/AndroidRuntime(1789):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
11-06 15:16:17.199: E/AndroidRuntime(1789):     at dalvik.system.NativeStart.main(Native Method)

      

*

0


source to share


1 answer


Instead of just looking at errors in logcat, look at the warnings. I believe that you will see a warning similar to the following:

WARN CursorWindow Window is full: requested allocation x bytes, free space x bytes, window size x bytes

      

This means that your cursor object is larger than the allocated size, which is usually 2MB. Your cursor is loading a couple of images / blobs, which can cause it to grow larger than 2MB.

Solutions

1 - Read the images one by one. Instead of doing a query that selects everything, eg. SELECT * FROM contacts ... change it to read one or two images at a time, indexing the results. You can perhaps train how much space you need by looking at the size of your images.



2 - Do not save images in the database. It might be better to store the images in a directory on the SD card and then just store the URIs in the db and read them into the cursor. then leave the image decoding in your application, which has much more memory to work with than your cursor object.

Solution 1 implementation

So I finally sat down, wrote the code and tested it and it works great. So here is the code for solution 1. It works great for me, obviously your implementation might be different depending on how you store and retrieve data, etc. So here goes

I added comments and changed the code to make it easier to understand.

        //This is the part of my Sync method where I start pulling images from the database. 
        if(isSyncNeeded)
        {
            android.util.Log.w("     CURSOR FIXES     ", "BEGIN...");
            databaseHelperimages = new Handler_Database(Screen_Main.this);
            SQLiteDatabase dbimages = databaseHelperimages.getReadableDatabase();

            //I store my data in arraylists when I read the from the db.
            Session.arraylist_pictures_1 = new ArrayList<String>();
            Session.arraylist_pictures_2 = new ArrayList<String>();

            //Do all your reading here...
            // I have another query before this where I get the id of each row in my database. And here, I say, for each id in my database, get the corresponding image in that row.
            for (String id : Session.arraylist_allsubmissions_id)
            {
                Cursor c1 = dbimages.rawQuery("SELECT picture1 FROM submissions WHERE id" + " = " + id, null);
                if(c1.getCount() > 0) 
                {
                    if(c1.moveToFirst())
                    {
                        do
                        {
                            try
                            {
                                int index = c1.getColumnIndex("picture1");
                                String entry = c1.getString(index);
                                Session.arraylist_pictures_1.add(entry);
                            }
                            catch (IllegalStateException e)
                            {
                                //Do Nothing
                            }
                            catch (NullPointerException e)
                            {
                                //Do Nothing
                            }
                        }
                        while(c1.moveToNext());
                    }
                }
                c1.close();

                Cursor c2 = dbimages.rawQuery("SELECT picture2 FROM submissions WHERE id" + " = " + id, null);
                if(c2.getCount() > 0) 
                {
                    if(c2.moveToFirst())
                    {
                        do
                        {
                            try
                            {
                                int index = c2.getColumnIndex("picture2");
                                String entry = c2.getString(index);
                                Session.arraylist_pictures_2.add(entry);
                            }
                            catch (IllegalStateException e)
                            {
                                //Do Nothing
                            }
                            catch (NullPointerException e)
                            {
                                //Do Nothing
                            }
                        }
                        while(c2.moveToNext());
                    }
                }
                c2.close();

                //Continue doing this for all your images.
            }
            databaseHelperimages.close();
            dbimages.close();
            android.util.Log.w("     CURSOR FIXES     ", "END...");
        }

      

+8


source







All Articles