在android中尝试保存和检索图像到数据库时出错

Jos*_*sef 1 database android

我是Android的新手,我的应用程序出错了.

我的应用做了以下事情:

1-用户可以选择从相机或图库导入图像.

2-所有图像都保存在数据库中,用户可以在另一个活动的列表视图中查看所有图像.

当我点击菜单栏图标传递到另一个活动,看到应用程序崩溃的所有图像,我在日志文件中收到以下错误:

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.
Run Code Online (Sandbox Code Playgroud)

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

    }



}
Run Code Online (Sandbox Code Playgroud)

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

    }


}
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

列表视图中每行的layout_row.xml布局

<?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>
Run Code Online (Sandbox Code Playgroud)

我花了很多时间搜索解决方案,但没找到.

谢谢你的到来!!!

完整的日志文件:

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)
Run Code Online (Sandbox Code Playgroud)

*

Jan*_*pan 10

而不只是查看logcat中的错误,请查看警告.我相信您会看到类似于以下内容的警告:

WARN CursorWindow Window is full: requested allocation x bytes, free space x bytes, window size x bytes
Run Code Online (Sandbox Code Playgroud)

这意味着您的游标对象大于分配的大小,通常为2Mb.您的光标正在加载几个图像/ blob,这可能会导致它大于2Mb.

解决方案

1 - 逐个阅读图像.而不是执行选择所有内容的查询,例如SELECT*FROM contacts ...将其更改为通过索引结果一次读取一个或两个图像.您可以通过查看图像的大小来锻炼所需的空间.

2 - 不要将图像保存在数据库中.最好将图像保存在SD卡上的目录中,然后将URI保存到数据库中并将其读入光标.然后将图像解码留给你的应用程序,它比你的光标对象有更多的内存.

解决方案1的实施

所以我终于坐下来编写了代码并进行了测试,效果很好.所以这里是解决方案1的代码.它对我来说很好,显然你的实现可能会有所不同,具体取决于你如何存储和检索你的数据等.所以这里去了

我已经添加了注释并修改了代码,以便更容易理解.

        //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...");
        }
Run Code Online (Sandbox Code Playgroud)