Использование ViewBinder, SimpleCursorAdapter, SQLite для отображения снимков, сделанных камерой, в ListView

Предполагается, что эта программа должна делать, когда она запускается, и когда щелкается значок камеры на панели действий, открывается камера, и если пользователь делает снимок и просит сохранить его, изображение будет сохранено в базе данных. и фотография будет отображаться на главной странице в виде миниатюры в ListView сразу после исчезновения экземпляра камеры.

Однако до сих пор я получал SQLiteException, говорящий "неизвестная ошибка (код 0): INTEGER данные в nativeGetBlob".

Каждый раз, когда я выполнял свой код после некоторой отладки, я полностью удалял свою базу данных, чтобы у нее был новый старт. И в моей базе данных процесс сохранения, по-видимому, прошел нормально, потому что я использую adb для проверки своей базы данных, и моя командная строка показывает, что таблица имеет два столбца, первый - _id, а второй - столбец изображений, изображения хранятся в форма.PNG. как byte[], и идентификаторы автоматически инкрементируются.

Мне удалось получить только одно тестовое изображение для отображения в виде простого ImageView (с тем же кодом хранения SQLite), но когда я пытаюсь показать его в ListView, используя ViewBinder и SimpleCursorAdapter, я получаю исключение SQLiteException. Я прочитал много других вопросов здесь и пробовал их решения в течение целого дня, но все еще застрял. Любой эксперт, который знает, как отладить мою программу?

Вот мои коды до сих пор:

MainActivity.java:

import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.provider.MediaStore;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import java.io.ByteArrayOutputStream;


public class MainActivity extends ActionBarActivity {

    static final int REQUEST_IMAGE_CAPTURE = 1;
    SQLiteDatabase db;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        db = this.openOrCreateDatabase("images.db", Context.MODE_PRIVATE, null);
        db.execSQL("create table if not exists tb (  _id INTEGER PRIMARY KEY AUTOINCREMENT, image blob)");
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        //dispatchTakePictureIntent();
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            //Calling dispatchTakePictureIntent to start the camera activity
            dispatchTakePictureIntent();
            return true;
        }

        return super.onOptionsItemSelected(item);

    }


    private void dispatchTakePictureIntent() {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
        }
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
            /*Bundle extras = data.getExtras();
            Bitmap imageBitmap = (Bitmap) extras.get("data");
            ImageView thumb1 = (ImageView) findViewById(R.id.thumb1);
            thumb1.setImageBitmap(imageBitmap);*/
            ////////////////////////////////////////////////////////////////////////

            Bundle extras = data.getExtras();
            Bitmap imageTaken = (Bitmap) extras.get("data");

            ContentValues values = new ContentValues();
            //calculate how many bytes our image consists of.
           /* int bytes = imageTaken.getByteCount();
            //or we can calculate bytes this way. Use a different value than 4 if you don't use 32bit images.
            //int bytes = b.getWidth()*b.getHeight()*4;

            ByteBuffer buffer = ByteBuffer.allocate(bytes); //Create a new buffer
            imageTaken.copyPixelsToBuffer(buffer); //Move the byte data to the buffer

            byte[] toValuesPut = buffer.array(); //Get the underlying array containing the data.
            */
           byte[] toValuesPut = this.getBytes(imageTaken);
            values.put("image", toValuesPut);
            db.insert("tb", null, values);
            getImage();

            ///////////////////////////////////////////////////////////////

            db.close();
        }

    }

    protected void getImage(){
        Cursor c = db.rawQuery("select * from tb", null);
        if (c.moveToNext()){
            //byte[] image = c.getBlob(0);
            //Bitmap bmp = BitmapFactory.decodeByteArray(image, 0, image.length);
            //ImageView thumb1 = (ImageView) findViewById(R.id.thumb1);
            // thumb1.setImageBitmap(bmp);
            ListView listView = (ListView) findViewById(R.id.sampleListView);
            SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
                    R.layout.photos, c, new String[] { "_id", "image" }, new int[]{R.id.col1, R.id.col2});

            SimpleCursorAdapter.ViewBinder viewBinder = new SimpleCursorAdapter.ViewBinder() {

                public boolean setViewValue(View view, Cursor cursor,
                                            int columnIndex) {
                    ImageView image = (ImageView) view;
                    byte[] byteArr = cursor.getBlob(columnIndex);
                    image.setImageBitmap(BitmapFactory.decodeByteArray(byteArr, 0, byteArr.length));
                    return true;
                }
            };
            ImageView image = (ImageView) findViewById(R.id.editimage);
            viewBinder.setViewValue(image, c, c.getColumnIndex("_id"));
            adapter.setViewBinder(viewBinder);
            listView.setAdapter(adapter);

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

}

activity_main.xml:

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

<TableRow
    android:id="@+id/tableRow1"
    android:layout_width="793dp"
    android:layout_height="wrap_content"
    android:layout_weight="0.23" >

    <TextView android:id="@+id/col1"
        android:layout_height="fill_parent"
        android:layout_width="wrap_content"
        android:width="50dp"
        android:textSize="18sp"

        />
    <TextView android:id="@+id/col2"
        android:layout_height="fill_parent"
        android:layout_width="wrap_content"
        android:width="150dp"
        android:textSize="18sp"
        />
    <ImageView android:id="@+id/editimage"

        android:clickable="true"
        android:onClick="ClickHandlerForEditImage"
        android:layout_width="35dp"
        android:layout_height="35dp"/>

</TableRow>

</LinearLayout>

menu_main.xml:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
    <item android:id="@+id/action_settings"
        android:title="@string/action_settings"
        android:icon="@drawable/camera"
        android:orderInCategory="100"
        app:showAsAction="ifRoom" />
</menu>

listview.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">
    <ListView
        android:id="@+id/sampleListView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_marginBottom="10dp"
        android:layout_marginTop="5dp"
        android:background="@android:color/transparent"
        android:cacheColorHint="@android:color/transparent"
        android:divider="#CCCCCC"
        android:dividerHeight="1dp"
        android:paddingLeft="2dp" >
    </ListView>

</LinearLayout>

photos.xml:

<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/thumb2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="10dp"
    android:textSize="24sp"/>

Logcat:

Caused by: android.database.sqlite.SQLiteException: unknown error (code 0): INTEGER data in nativeGetBlob
            at android.database.CursorWindow.nativeGetBlob(Native Method)
            at android.database.CursorWindow.getBlob(CursorWindow.java:403)
            at android.database.AbstractWindowedCursor.getBlob(AbstractWindowedCursor.java:45)
            at hiew1.is2.byuh.edu.mydailyselfie.MainActivity$1.setViewValue(MainActivity.java:133)
            at hiew1.is2.byuh.edu.mydailyselfie.MainActivity.getImage(MainActivity.java:139)
            at hiew1.is2.byuh.edu.mydailyselfie.MainActivity.onActivityResult(MainActivity.java:108)
            at android.app.Activity.dispatchActivityResult(Activity.java:6192)
            at android.app.ActivityThread.deliverResults(ActivityThread.java:3573)
            at android.app.ActivityThread.handleSendResult(ActivityThread.java:3620)
            at android.app.ActivityThread.access$1300(ActivityThread.java:151)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1352)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5257)

огромное спасибо

1 ответ

Решение

Возможно, вы можете попробовать следовать этому примеру, не используя ViewBinder и SimpleCursorAdapter. Просто используйте метод bindblob() и курсор:

Как сохранить изображение в базе данных SQLite

Другие вопросы по тегам