I understand this question has been asked many times before, but in this case it is different since the error only occurs when attempting to save an image to the database while the other questions weren't dealing with images. If there is one please comment with the link.
First off I am only posting the code which I think is necessary, so if I missed some code or anything please let me know. I have a note-taking app which stores 2 different EditText fields as the note title and note body. That works fine. I tried adding functionality to add, store, and retrieve an image from the SQLite database. This is the code from my EditNoteActivity class that runs during a "store" operation after the user finishes editing a note and presses the back button to go to the MainActivity class.
private void updateNote(String noteText, String titleText) {
Log.d("Img", "updateNote");
ContentValues values = new ContentValues();
ImageView img = (ImageView) findViewById(R.id.imageView);
byte[] data;
if (img.getDrawable() != null) {
Log.d("Img", "updateNote ----- image here");
Bitmap bitmap = ((BitmapDrawable)img.getDrawable()).getBitmap();
// data = getBitmapAsByteArray(bitmap);
data = DbBitmapUtility.getBytes(bitmap);
} else {
Log.d("Img", "updateNote ----- image not here");
data = null;
}
values.put(DBOpenHelper.NOTE_IMAGE, data);
values.put(DBOpenHelper.NOTE_BODY, noteText);
values.put(DBOpenHelper.NOTE_TITLE, titleText);
// reusing noteFilter value to make sure you're only updating 1 selected row
getContentResolver().update(NoteProvider.CONTENT_URI, values, noteFilter, null);
Toast.makeText(this, R.string.note_updated, Toast.LENGTH_SHORT).show();
setResult(RESULT_OK); // send message to MainActivity saying something has changed, update content in list
}
If I don't add an image to the ImageView, then I can save the note no problem. But if I add an image and then try to go back to MainActivity, the program crashes on the following lines:
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
cursorAdapter.swapCursor(data); // crashes here
}
and it also crashes on the class declaration:
public class MainActivity extends AppCompatActivity
Since I used the Log.d a lot, it does say in the logcat the following:
updateNote updateNote ----- image here
like it should if you follow the code in the updateNote method. Here is the getBytes method in the DbBitmapUtility class which I use to get a byte array for storing the image as a BLOB:
// convert from bitmap to byte array
public static byte[] getBytes(Bitmap bitmap) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 0, stream);
return stream.toByteArray();
}
Lastly here is my database setup:
public static final String TABLE_NOTES = "notes";
public static final String NOTE_ID = "_id";
public static final String NOTE_TITLE = "noteTitle";
public static final String NOTE_BODY = "noteBody";
public static final String NOTE_IMAGE = "noteImage";
public static final String NOTE_CREATED = "noteCreated";
public static final String[] ALL_COLUMNS =
{NOTE_ID, NOTE_TITLE, NOTE_BODY, NOTE_IMAGE, NOTE_CREATED};
// SQL to create table
private static final String TABLE_CREATE =
"CREATE TABLE " + TABLE_NOTES + " (" +
NOTE_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
NOTE_TITLE + " TEXT, " +
NOTE_BODY + " TEXT, " +
NOTE_IMAGE + " BLOB, " +
NOTE_CREATED + " TEXT default CURRENT_TIMESTAMP" +
")";
Here are the errors:
E/AndroidRuntime: FATAL EXCEPTION: main Process: com.beauty.comp_eng.mynote, PID: 16435 java.lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it. at android.database.CursorWindow.nativeGetLong(Native Method) at android.database.CursorWindow.getLong(CursorWindow.java:511) at android.database.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:75) at android.database.CursorWrapper.getLong(CursorWrapper.java:127) at android.widget.CursorAdapter.getItemId(CursorAdapter.java:259) at android.widget.AdapterView.rememberSyncState(AdapterView.java:1243) at android.widget.AdapterView$AdapterDataSetObserver.onChanged(AdapterView.java:830) at android.widget.AbsListView$AdapterDataSetObserver.onChanged(AbsListView.java:6470) at android.database.DataSetObservable.notifyChanged(DataSetObservable.java:37) at android.widget.BaseAdapter.notifyDataSetChanged(BaseAdapter.java:50) at android.widget.CursorAdapter.swapCursor(CursorAdapter.java:381) at com.beauty.comp_eng.mynote.MainActivity.onLoadFinished(MainActivity.java:200) at com.beauty.comp_eng.mynote.MainActivity.onLoadFinished(MainActivity.java:25) at android.support.v4.app.LoaderManagerImpl$LoaderInfo.callOnLoadFinished(LoaderManager.java:479) at android.support.v4.app.LoaderManagerImpl$LoaderInfo.onLoadComplete(LoaderManager.java:447) at android.support.v4.content.Loader.deliverResult(Loader.java:126) at android.support.v4.content.CursorLoader.deliverResult(CursorLoader.java:105) at android.support.v4.content.CursorLoader.deliverResult(CursorLoader.java:37) at android.support.v4.content.AsyncTaskLoader.dispatchOnLoadComplete(AsyncTaskLoader.java:249) at android.support.v4.content.AsyncTaskLoader$LoadTask.onPostExecute(AsyncTaskLoader.java:77) at android.support.v4.content.ModernAsyncTask.finish(ModernAsyncTask.java:466) at android.support.v4.content.ModernAsyncTask.access$400(ModernAsyncTask.java:48) at android.support.v4.content.ModernAsyncTask$InternalHandler.handleMessage(ModernAsyncTask.java:483) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5525) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
I thought I was storing the image properly, as I found that's the way they did it in many other stackoverflow answers but it's not working. And I noticed it said
Couldn't read row 0, col 0 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
Why are no records being returned if there are already plain notes without images stored in the database?