I'm seeing a crash report for this occassionally:
Fatal Exception: java.lang.IllegalStateException: Couldn't read row 1127, col 0 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
at android.database.CursorWindow.nativeGetLong(CursorWindow.java)
at android.database.CursorWindow.getLong(CursorWindow.java:511)
at android.database.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:75)
at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:220)
at android.database.AbstractCursor.moveToNext(AbstractCursor.java:245)
at android.database.CursorWrapper.moveToNext(CursorWrapper.java:166)
at com.anthonymandra.util.ImageUtils.cleanDatabase(SourceFile:381)
Apparently the moveToNext
is failing mid-loop (note row 1127). The loop removes entries that represent files that can no longer be found.
final ArrayList<ContentProviderOperation> operations = new ArrayList<>();
try( Cursor cursor = c.getContentResolver().query(Meta.CONTENT_URI, null, null, null, null))
{
if (cursor == null)
return;
final int uriColumn = cursor.getColumnIndex(Meta.URI);
final int idColumn = cursor.getColumnIndex(BaseColumns._ID);
while (cursor.moveToNext())
{
String uriString = cursor.getString(uriColumn);
if (uriString == null) // we've got some bogus data, just remove
{
operations.add(ContentProviderOperation.newDelete(
Uri.withAppendedPath(Meta.CONTENT_URI, cursor.getString(idColumn))).build());
continue;
}
Uri uri = Uri.parse(uriString);
UsefulDocumentFile file = UsefulDocumentFile.fromUri(c, uri);
if (!file.exists())
{
operations.add(ContentProviderOperation.newDelete(Meta.CONTENT_URI)
.withSelection(getWhere(), new String[]{uriString}).build());
}
}
}
c.getContentResolver().applyBatch(Meta.AUTHORITY, operations);
Any idea how a cursor could fail mid-loop like that?
You appear to be making a fairly large query: at least 1127 rows, and for all possible columns (despite the fact that you are only using two of them). And, during your work with that Cursor
, you are doing disk I/O and/or IPC back to the ContentProvider
, assuming that UsefulDocumentFile
is related to Android's DocumentFile
.
As Prakash notes, the Cursor
that you get back may contain only a subset of the information. As soon as you try advancing past that point, the Cursor
needs to go back to the data source and get the next window of results. I can see you running into this sort of problem if there has been a substantial change in the data while this work has been going on (e.g., there are now fewer than 1127 rows).
I suggest that you:
Constrain the columns that you get back to the subset that you need, and
Avoid the I/O during the loop (e.g., spin through the Cursor
to build up an ArrayList<Pair>
or something, close the Cursor
, then iterate over the list)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With