【问题标题】:Error while trying save and retrieve images into database in android尝试将图像保存和检索到android中的数据库时出错
【发布时间】:2014-11-14 00:32:54
【问题描述】:

我是 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.

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 列表视图中每一行的布局

<?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>

我浪费了很多时间寻找解决方案,但没有找到。

谢谢你!

完整的日志文件:

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)

*

【问题讨论】:

  • 如果您不对它们进行任何操作,如果它们已经在设备上,为什么要将它们保存到数据库中?为什么不直接将 URI 保存到数据库并加载要在列表视图中显示的文件?
  • 我这样做是为了练习使用数据库。
  • 当我搜索日志文件中的错误时,我发现这是关于数据库中不存在的列,但我不太了解。
  • 那么你可能应该发布错误
  • 日志会告诉你。发布完整的 logcat。

标签: android database


【解决方案1】:

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

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

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

解决方案

1 - 一张一张地阅读图像。而不是进行选择所有内容的查询,例如SELECT * FROM contacts ... 通过索引结果将其更改为一次读取一到两个图像。您可能可以通过查看图像的大小来确定需要多少空间。

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

方案一的实现

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

我已经放入了 cmets 并修改了代码以便更容易理解。

        //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...");
        }

【讨论】:

  • 非常感谢。您可以发布解决方案 1 的示例吗?
  • @user242201 ,我可能可以在一周内发布一个完整的示例,因为我在类似的项目中遇到了同样的问题并且仍然需要实现它。但是,您可以更改查询以限制结果。看看这个线程如何实现这个:stackoverflow.com/a/22067940/1518916。然后把它放在一个循环中,直到你所有的图像都被加载。所以总而言之,你会限制你的光标结果,使光标的大小更小,然后将这些结果保存到一个列表中,或者你想要的,然后回收光标对象并继续该过程,直到所有图像都加载完毕。跨度>
  • @user242201 请看我上面的回答,我已经为第 1 部分添加了解决方案。我已经完成了代码,它对我有用。如果有帮助,请告诉我。另外,如果您有任何问题,请告诉我。但是,将查询分成多个部分/游标对我来说是诀窍。我担心所有游标对象都共享内存,但幸运的是他们没有! :)
  • 首先,非常感谢您为我发布您的答案。我花了好几个小时,但最后我上周自己解决了我的问题。我的应用程序从相机或图库中获取图像,并将其放入 Sqlite 数据库中。我认为,自己保存图像是这样做的好方法,因为 - 如果图像将从手机中删除并且我尝试过并且它起作用了怎么办。我将图像导入到我的应用程序中,然后删除了手机图库中的所有图像,它们仍保留在我的数据库中。
  • 如果你有时间我可以把我项目的 zip 文件夹发给你,你会告诉我你的想法。只是写你的电子邮件地址,然后再一次 - 谢谢ssssssssssssssssssssssssssssssssssssssssssssssssssssss! ;-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-15
  • 2021-10-13
  • 2014-01-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多