Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sharing sqlite database between multiple Android Activities

Tags:

android

sqlite

Can two or more Android Activities open an sqlite3 database for write?

I have two Activities that need to insert data into the same sqlite database. When the second Activity calls SQLiteOpenHelper.getWriteableDatabase() an IllegalStateException is thrown with the message "SQLiteDatabase created and never closed".

I've been able to avoid the Exception by making my database object a singleton but I'm thinking there must be a better way.

Thanks,

John

like image 538
John in MD Avatar asked Oct 12 '09 21:10

John in MD


People also ask

Can multiple applications use the same SQLite database?

Yes, they can!

Can SQLite handle multiple users?

Yes SQLite can support multiple users at once. It does however lock the whole database when writing, so if you have lots of concurrent writes it is not the database you want (usually the time the database is locked is a few milliseconds - so for most uses this does not matter).

Can you share SQLite database?

To transfer an SQLite database found on the development computer to an Android device, the database can be added into the apk archive of the application. This operation can be performed when creating the Android archive, in the "Integrating files" screen.

Can multiple processes write to SQLite?

SQLite allows multiple processes to have the database file open at once, and for multiple processes to read the database at once. When any process wants to write, it must lock the entire database file for the duration of its update.


2 Answers

There's never really more than one Activity running at a time. The easy way to fix this would be to have the first Activity close it's connection before starting the second Activity. You can do this in the onPause() then reopen it in the onResume(). Something like this (very psuedo-code):

MyActivity {
    OnResume()
        open connection to database
    OnPause()
        close connection to database
}

This way you're never trying to have more than one connection at a time and the connection is always available.

like image 171
Jeremy Logan Avatar answered Sep 22 '22 21:09

Jeremy Logan


I also have multiple Activities and each Activity opens its own database connection. I keep the main Activity alive while I start other activities, and I call finish() on the child activities when I no longer need them.

What I am seeing is that a child Activity can successfully open a connection and query data while the main Actitity is still holding on to its DBAdapter. When the child Activity ends, the main Activity requeries any cursors that are open. This seems to happen automatically.

However, after clicking around on the user interface for a while, which causes my app to start and finish Activities, I will eventually get the exception:

ERROR/Database(17657): Leak found
ERROR/Database(17657): java.lang.IllegalStateException:
      /data/data/yourpackage/databases/yourdatabase 
      SQLiteDatabase created and never closed
ERROR/Database(17657): at android.database.sqlite.SQLiteDatabase.<init>
     (SQLiteDatabase.java:1694)

The exception is not from the Activity that is currently in the foreground, but from one that was finished a while ago. So, what happens is that the garbage collector is cleaning up and finding the open database connection. This does not affect the app - it continues to work fine and all queries from the foreground Activity return data.

The solution is simply to close the connection in the child Activity. The onDestroy() event is the right place to do that:

@Override    
protected void onDestroy() {        
    super.onDestroy();
    myAdapter.close();
}

Since I put this in all my child Activities, I no longer get the exception.

like image 44
cdonner Avatar answered Sep 23 '22 21:09

cdonner