Question

I released an update of my app and am getting a ton of errors from users and I can't recreate it or pin-point the problem.

Two errors I'm getting: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase

java.lang.IllegalStateException: database not open
Both are happening at

at com.jakar.package.dj.a(Unknown Source)
at com.jakar.package.fi.a(Unknown Source)
at com.jakar.package.AHost.onCreate(Unknown Source)

which maps to

at com.jakar.package.DBUserS.getUser(Unknown Source)
                                  saveUser
                                  getAllInfo
                                  cursorToInfo
at com.jakar.package.M.switchUser(Unknown Source)
                            requeryUser
                            createAlerts
                            addTab
                            hasScheduleData
                            getRandom
                            round
at com.jakar.workschedule.AHost.onCreate(Unknown Source)

In this version, there is a database upgrade, in which I perform three queries via db.execSql. It is not in a separate thread.

On every call to the database (except in the onUpgrade), I synchronize, then open it, run my code, then close it. I was having no problems until this upgrade and can't find the issue.

Any help would be greatly appreciated.

EDIT: To open my databas, I do:

if (helper==null)
    helper = new DBAdapter(context);
if (database==null){
     database = helper.getWritableDatabase();
} else if (!database.isOpen())
     database = helper.getWritableDatabase();

and to close:

helper.close();
helper = null;
database = null;

Example method for getting info:

    public DBUserC getUser(int _id){
        synchronized (DBAdapter.LOCK){
            openDB(context);//this is the open code above
            Cursor cursor = M.database.query(DBUserHelper.TABLE_USERS,
                    VUser.allColumns, DBUserHelper.COLUMN_ID + " = '"+_id+"'", null, null, null, null);
            DBUserC user;
            if (cursor.moveToFirst()){
                user = cursorToInfo(cursor);//does not contain DB operations
            } else{
                user = newUser(); ////does not contain Database operations
            }
            cursor.close();
            closeDB();//This is the close code above
            return user;
        }
    }
Was it helpful?

Solution 2

I could not recreate issue because in testing, I was upgrading from DB version 3 to version 4. Many of my users were upgrading from version 2 to version 4. Some of the code for upgrading from 2 to 3 was method-based. I ended up changing some of those methods for version 4, which broke the version 3 upgrade. I then was getting a caught exception from a cursorToObject() method I had, which caused the database.close to be skipped and then I got the sqlite exception

OTHER TIPS

I do know for a fact that the java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase comes when you don't actually close the database properly, which does not necessarily mean you closing your database in the current activity, this may stem from any other activity that tries to access the database.

Also when you open a database, you must close the database on your other activity lifecycle events as well, for example:

@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    ...
    db.open();
    //some operation 
    db.close();
}

@Override
protected void onDestroy() {
    // TODO Auto-generated method stub
    super.onDestroy();
    if(db != null)
        db.close();
}

@Override
protected void onPause() {
    // TODO Auto-generated method stub
    super.onPause();
    if(db != null)
        db.close();
}

@Override
protected void onResume() {
    // TODO Auto-generated method stub
    super.onResume();
    db.open();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top