Search code examples
androidsqlitecursor

Application did not close cursor, despite getting closed


I have an SQLite database in my Android Application. When I do one operation I always get a Finalizing a Cursor that has not been deactivated or closed. Here is the method:

public String getKey(){
    net.sqlcipher.database.SQLiteDatabase db = this.getWritableDatabase(Login.authPass);
    String selectQuery = "SELECT  * FROM " + STABLE;
    Cursor cursor = db.rawQuery(selectQuery, null); //This is the line that throws the exception
    String s = cursor.getString(1);
    cursor.close();
    db.close();
    return s;
}

It is really frustrating, because I am going to close the Cursor, it just throws an exception before it even gets there. Also I don't get how anything I'm doing on this line is considered finalizing the cursor. Thank you.

Edited to add Logcat:

02-24 12:28:26.522 12756-12765/com.itsmr.dre2k14 E/Cursor﹕ Finalizing a Cursor that has not been deactivated or closed. database = /data/data/com.itsmr.dre2k14/databases/keys.db, table = null, query = SELECT * FROM keys net.sqlcipher.database.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here at net.sqlcipher.database.SQLiteCursor.(SQLiteCursor.java:217) at net.sqlcipher.database.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:53) at net.sqlcipher.database.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1447) at net.sqlcipher.database.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1416) at com.itsmr.dre_android_clean.KeyTable.getKey(KeyTable.java:41) at com.itsmr.dre_android_clean.Login.noConnectValidate(Login.java:218) at com.itsmr.dre_android_clean.Login.connect(Login.java:97) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at android.view.View$1.onClick(View.java:3964) at android.view.View.performClick(View.java:4640) at android.view.View$PerformClick.run(View.java:19421) at android.os.Handler.handleCallback(Handler.java:733) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5476) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084) at dalvik.system.NativeStart.main(Native Method)


Solution

  • It looks like you should call moveToFirst() to move the cursor to the first row in the database.

    Also, just making sure that this is what you intended, calling cursor.getString(1); will get the second column in the current row, since it is zero based. http://developer.android.com/reference/android/database/Cursor.html#getString(int)

    Also, best practice is to make sure that a cursor is not null before you use it, also use try/catch for database operations.

    public String getKey(){
     String s = null;
    
     try{
      net.sqlcipher.database.SQLiteDatabase db = this.getWritableDatabase(Login.authPass);
      String selectQuery = "SELECT  * FROM " + STABLE;
      Cursor cursor = db.rawQuery(selectQuery, null);
      if (cursor != null && cursor.moveToFirst()){
        s = cursor.getString(1);
      }
    
     } catch (Exception ex) {
        Log.e("MyApp", ex.getMessage());
     } finally
     {
        if (cursor != null) {
           cursor.close();
    
        }
        if (db != null) {
            db.close();
        }
    
     }
    
    return s;
    }
    

    This post might be helpful too: cursor.getstring() is getting the wrong field in the database