I'm making an Kiosk app that use database. The app is running all time in foreground. The app have many threads that using one shared DataBaseHelper instance. the app works flawlessly but most of the time after 5 or 6 hour, I encounter these exceptions then app crashes:
E/DataBaseHelper﹕ Cursor window allocation of 2048 kb failed. # Open Cursors=1 (# cursors opened by this proc=1)
E/CursorWindow﹕ Could not allocate CursorWindow '/data/user/0/com.kios.frm/databases/YadProjectDB.db' of size 2097152 due to error -24.
E/SQLiteLog﹕ (14) cannot open file at line 30192 of [00bb9c9ce4]
E/SQLiteLog﹕ (14) statement aborts at 16: [SELECT number FROM sms LIMIT 5] unable to open database file
E/SQLiteQuery﹕ exception: unable to open database file (code 14);
query: SELECT number FROM sms LIMIT 5E/SQLiteLog﹕ (14) os_unix.c:30192: (24)
open(/data/user/0/com.kiosk.frm/databases/YadProjectDB.db-journal)-
I closed cursor properly but still getting those exceptions. what are those exceptions? what is the cause of those exceptions?
MainActivity
private DataBaseHelper db = null; // Global
MainActivity onCreate method:
db = new DataBaseHelper(this);
new Thread(new Runnable() {
@Override
public void run() {
while (threadRunningFlag) {
Cursor result = null;
try {
result = db.getData("SELECT " + DataBaseHelper.SMS_COLUMN_PHONE_NUMBER + " FROM " + DataBaseHelper.SMS_TABLE_NAME + " LIMIT 5");
if (result != null && result.getCount() > 0) {
while (!result.isAfterLast()) {
String phoneNumber = result.getString(result.getColumnIndex(DataBaseHelper.SMS_COLUMN_PHONE_NUMBER));
// ...
result.moveToNext();
}
}
}catch (Exception e) {
Log.e(TAG, "err->" + e.getLocalizedMessage());
}finally {
if (result != null) {
result.close();
result = null;
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e(TAG, e.getMessage());
}
}
}
}).start();
DataBaseHelper class:
public class DataBaseHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "YadProjectDB.db";
public static final String SMS_TABLE_NAME = "sms";
public static final String SMS_COLUMN_PHONE_NUMBER = "number";
public static final String SMS_COLUMN_SMS_TEXT = "message";
public static final String BLACK_LIST_TABLE_NAME = "blackList";
public static final String BLACK_LIST_COLUMN_ID = "id";
public static final String BLACK_LIST_COLUMN_PHONE_NUMBER = "number";
private final String TAG = "DataBaseHelper";
public DataBaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate( SQLiteDatabase db ) {
String command = "CREATE TABLE "
+ SMS_TABLE_NAME
+ "("
+ SMS_COLUMN_PHONE_NUMBER + " TEXT,"
+ SMS_COLUMN_SMS_TEXT + " TEXT,"
+ ")";
try {
db.execSQL(command);
}catch (Exception e) {
Log.e(TAG, "err->" + e.getMessage());
}
command = "CREATE TABLE "
+ BLACK_LIST_TABLE_NAME
+ "("
+ BLACK_LIST_COLUMN_PHONE_NUMBER + " TEXT,"
+ ")";
try {
db.execSQL(command);
}catch (Exception e) {
Log.e(TAG, "err->" + e.getMessage());
}
}
public boolean insertToSms(String number, String message, String fileName, Integer uploadFlag, Integer blackList, Integer pictureFlag)
{
final SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(SMS_COLUMN_PHONE_NUMBER, number);
contentValues.put(SMS_COLUMN_SMS_TEXT, message);
try {
db.insert(SMS_TABLE_NAME, null, contentValues);
return true;
}catch (Exception e) {
Log.e(TAG, "err->" + e.getMessage());
return false;
}
}
public Cursor getData(String query){
final SQLiteDatabase db = getReadableDatabase();
Cursor res = null;
try {
res = db.rawQuery(query, null);
res.moveToFirst();
return res;
}catch (Exception e) {
Log.e(TAG, "err->" + e.getMessage());
if (res != null) {
res.close();
res = null;
}
}
return null;
}
}
This is looks the same issue as SQLite Android Database Cursor window allocation of 2048 kb failed
Your error says: "Open Cursors"
The answer in the above question explains it:
Most often the cause for this error are non closed cursors. Make sure you close all cursors after using them (even in the case of an error).
Cursor cursor = null;
try {
cursor = db.query(...
// do some work with the cursor here.
} finally {
// this gets called even if there is an exception somewhere above
if(cursor != null)
cursor.close();
}