Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Open/Close SQLite db in Android Properly

I have an app that functions properly and does not force close or crash. But when I look at LogCat, it occasionally gives me this:

05-20 15:24:55.338: E/SQLiteDatabase(12707): close() was never explicitly called on database '/data/data/com.---.--/databases/debt.db' 
05-20 15:24:55.338: E/SQLiteDatabase(12707): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here

a little ways down...

05-20 15:24:55.338: E/System(12707): Uncaught exception thrown by finalizer
05-20 15:24:55.338: E/System(12707): java.lang.IllegalStateException: Don't have database lock!

I am not sure when I should be opening and closing my Database?

I have a Main activity that is simply a splash screen. It then goes into an activity that calls a ListView using info from the DB; so it is at this activity where the DB is first opened.

There is also one other Activity where the DB is required that branches off the one with the ListVeew. When am I supposed to be opening and closing this? Word seems to be that I simply need to open once, and then close when the app is "paused", "stopped" or "destroyed".

If this is the case, where do I put the db.close() method... in the Splash Screen Main Activity where onStop, etc is located? or the same Activity as the one that opens the DB? or.. is there another place?

UPDATE:

This is the line in code that the error keeps pointing to:

public void open() throws SQLException {
    database = dbHelper.getWritableDatabase();
}
like image 979
TheLettuceMaster Avatar asked May 20 '12 22:05

TheLettuceMaster


People also ask

How do I open a SQLite database?

Open a command prompt (cmd.exe) and 'cd' to the folder location of the SQL_SAFI. sqlite database file. run the command 'sqlite3' This should open the SQLite shell and present a screen similar to that below.

How can I recover SQLite database in Android?

We can retrieve anything from database using an object of the Cursor class. We will call a method of this class called rawQuery and it will return a resultset with the cursor pointing to the table. We can move the cursor forward and retrieve the data. This method return the total number of columns of the table.


2 Answers

If you're using an instance of a DatabaseHelper class, and after you initialize the DBHelper object, every time you do work in the database you should call the open method before you do work, then create a new cursor, query the database, do work with the information you just stored in the cursor, when you're done close the cursor, then close the database. For example if you wanted to grab every item in a database you would do something like :

...    
DataBaseHelper db = new DataBaseHelper(this);
... 
db.open();
Cursor cursor = db.getAllItems(); 
maxCount = cursor.getCount(); 
Random gen = new Random();
row = gen.nextInt(maxCount); // Generate random between 0 and max
if (cursor.moveToPosition(row)) {
    String myString = cursor.getString(1);  //here I want the second column
    displayString(myString); //private method
}
cursor.close();
db.close(); 

getAllItems is a public method in my DatabaseHelper, it looks like this in case you were wondering

public Cursor getAllItems() {
    return db.query(DATABASE_TABLE, 
        new String[] {
            KEY_ROWID, 
            KEY_NAME
        }, 
        null, 
        null, 
        null, 
        null, 
        null);
}

This is how I access my database and I haven't gotten any of the errors you've got, and it works perfectly.

like image 137
Shikima Avatar answered Oct 17 '22 06:10

Shikima


I used to do the way @Shikima mentioned above but in complex applications which has many background services, multi-threading,etc it can get real tiresome when you have to manage many database instances and on top of that, opening and closing them.

To overcome this, I used the following method and it seems to be working fine.

1.

Declare and initialize an instance of YourDBHelperClass in your Application base class like this :

public class App extends Application {
  public static YourDBHelperClass db;

  @Override
  public void onCreate() {
    super.onCreate();
    db = new YourDBHelperClass(getApplicationContext());
    db.open();

  }
}

2.

In you activity, or any other place you want to use the DB, initialize the YourDBHelperClass object like this :

YourDBHelperClass db = App.db;

And then you can use the database anyway you want without having to worry about opening and closing it manually each time. The SQLiteOpenHelper takes care of the closing when the Application is destroyed

like image 33
desidigitalnomad Avatar answered Oct 17 '22 06:10

desidigitalnomad