27

I am getting below exception only in android 9, after reinstalling everything looks good,

Exception:

android.database.sqlite.SQLiteBlobTooBigException: Row too big to fit into CursorWindow requiredPos=0, totalRows=1...

Code:

Cursor cursor = database.query(......);
    if(cursor == null || cursor.getCount() < 0) { //Here is the error
        Log.d("Error", "count : null");
        return "";
    }

Edited:

java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:354)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
at java.util.concurrent.FutureTask.run(FutureTask.java:271)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)

Caused by: android.database.sqlite.SQLiteBlobTooBigException: Row too big to fit into CursorWindow requiredPos=0, totalRows=1
at android.database.sqlite.SQLiteConnection.nativeExecuteForCursorWindow(Native Method)
at android.database.sqlite.SQLiteConnection.executeForCursorWindow(SQLiteConnection.java:859)
at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:836)
at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:149)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:137)

Thanks in advance guys

Bikash Sahani
  • 312
  • 1
  • 3
  • 10
  • Can you edit your question to show the full stack trace, rather than just a single line from the stack trace. Adding the query may also be useful. – MikeT Aug 22 '18 at 04:43
  • i have edited my ans,check once, @MikeT – Bikash Sahani Aug 22 '18 at 14:04
  • did you find the solution?? I'm getting the same exception @Bikash Sahani. – Nirmal Prajapat Oct 01 '18 at 08:14
  • this is happening when ever, some one is upgrading to Oreo without uninstalling my app and keep continue using it, then this problem is coming, so at that time i am dropping the table and creating it again – Bikash Sahani Oct 31 '18 at 09:22
  • did you got any solution??? I get this problem only in android 9 pocof1 device? after upgrading to the pie in the first-time install I'm getting this error. after i reinstall its working fine – Aabauser Mar 05 '19 at 06:11
  • Is there any solution? – gencaysahinn Mar 11 '19 at 08:07

4 Answers4

20

This worked for me, you have to put it on your Main Activity.

try {
    Field field = CursorWindow.class.getDeclaredField("sCursorWindowSize");
    field.setAccessible(true);
    field.set(null, 100 * 1024 * 1024); //the 100MB is the new size
    } catch (Exception e) {
       e.printStackTrace();
    }
Enrique A
  • 309
  • 2
  • 2
  • This absolutely solved the problem, so thank you and +1. Quick follow-up question, does anyone know if this could trigger any cascaded external Runtime exceptions? IE, if a user has <100mb of free space on their device, will this throw an exception? Or work fine as it is in RAM? – PGMacDesign Feb 17 '22 at 22:15
3

Try this new constructor method above API 28. Maybe you should set a limited windowSizeBytes for CursorWindow and try-catch the exception.

Related cts code (https://android.googlesource.com/platform/cts/+/master/tests/tests/database/src/android/database/sqlite/cts/SQLiteCursorTest.java) :

    public void testRowTooBig() {
        mDatabase.execSQL("CREATE TABLE Tst (Txt BLOB NOT NULL);");
        byte[] testArr = new byte[10000];
        Arrays.fill(testArr, (byte) 1);
        for (int i = 0; i < 10; i++) {
            mDatabase.execSQL("INSERT INTO Tst VALUES (?)", new Object[]{testArr});
        }
        // Now reduce window size, so that no rows can fit
        Cursor cursor = mDatabase.rawQuery("SELECT * FROM TST", null);
        CursorWindow cw = new CursorWindow("test", 5000);
        AbstractWindowedCursor ac = (AbstractWindowedCursor) cursor;
        ac.setWindow(cw);
        try {
            ac.moveToNext();
            fail("Exception is expected when row exceeds CursorWindow size");
        } catch (SQLiteBlobTooBigException expected) {
        }
    }

Others:

Since this article was originally published, we’ve added new APIs in the Android P developer preview to improve the behavior above. The platform now allows apps to disable the ⅓ of a window heuristic and configure CursorWindow size.

Ref Link: https://medium.com/androiddevelopers/large-database-queries-on-android-cb043ae626e8

Sylvester Yao
  • 237
  • 2
  • 7
0

I found how to use length() and substr() to request only 1MB (the max for CursorWindow is 2MB), maybe it will help. Also, you could use context.getContentResolver().query() with a selection that only includes the _id column, that way you won't load data related to the other columns.

0

Try to scale bitmap:

Bitmap.createScaledBitmap
סטנלי גרונן
  • 2,917
  • 23
  • 46
  • 68
Qiang Yao
  • 9
  • 1