I'm having an issue with my SQLite database inside an Android app. It seems to happen every so often and I cannot reproduce it, but this is the report the Android Market gives.
Basically I have first a splash screen activity that starts by checking if all the needed data is in the database. If not, it will install the data in a asynchronous thread and close the db connection.
Then and only then can the main activity be started, which also opens and reads/writes the database.
This code is executed from the onCreate method of the splash screen activity:
dbWord = new WordDBAdapter(this, myUI);
dbWord.open();
if (dbWord.isDataInstalled()) {
dbWord.close();
databaseInstalled = true;
clickToStartView.setText(myUI.PRESS_TO_START);
clickToStartView.startAnimation(myBlinkAnim);
} else {
// If not, try to install in asynchronous thread
progressDialog = new ProgressDialog(this);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMessage(myUI.INSTALLING_DB);
progressDialog.setCancelable(false);
new InstallDBData().execute("");
}
The code for the asynchronous thread is:
private class InstallDBData extends AsyncTask<String, Integer, Integer> {
@Override
protected Integer doInBackground(String... arg0) {
progressDialog.setProgress(0);
dbWord.installData(0, getApplicationContext());
progressDialog.setProgress(20);
dbWord.installData(1, getApplicationContext());
progressDialog.setProgress(40);
dbWord.installData(2, getApplicationContext());
progressDialog.setProgress(60);
dbWord.installData(3, getApplicationContext());
progressDialog.setProgress(80);
dbWord.installData(4, getApplicationContext());
progressDialog.setProgress(100);
return 1;
}
protected void onPreExecute() {
progressDialog.show();
}
protected void onPostExecute(Integer x) {
dbWord.close();
progressDialog.hide();
databaseInstalled = true;
clickToStartView.setText(myUI.PRESS_TO_START);
clickToStartView.startAnimation(myBlinkAnim);
}
}
These are important parts of the WordDBAdapter class, which is also used by the main activity:
public class WordDBAdapter {
private DatabaseHelper mDbHelper;
private SQLiteDatabase mDb;
public WordDBAdapter open() throws android.database.SQLException {
mDbHelper = new DatabaseHelper(mCtx);
mDb = mDbHelper.getWritableDatabase();
return this;
}
public void close() {
mDbHelper.close();
}
...
}
I'm getting the following exceptions, which are similar but have a different message:
First type of error message:
java.lang.RuntimeException: Unable to start activity
ComponentInfo{example.flashcards.medical/com.example.flashcards.common.SplashWindow}:
android.database.sqlite.SQLiteException: database is locked: BEGIN EXCLUSIVE;
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1830)
....
Caused by: android.database.sqlite.SQLiteException: database is locked: BEGIN EXCLUSIVE;
at android.database.sqlite.SQLiteDatabase.native_execSQL(Native Method)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1870)
at android.database.sqlite.SQLiteDatabase.beginTransactionWithListener(SQLiteDatabase.java:602)
Second type of error message:
java.lang.RuntimeException: Unable to start activity
ComponentInfo{example.flashcards.medical/com.example.flashcards.common.SplashWindow}:
android.database.sqlite.SQLiteException: database is locked
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1768)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1784)
....
Caused by: android.database.sqlite.SQLiteException: database is locked
at android.database.sqlite.SQLiteDatabase.native_setLocale(Native Method)
at android.database.sqlite.SQLiteDatabase.setLocale(SQLiteDatabase.java:1987)
at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1855)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:820)
at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:854)
I would really like to not have to create a ContentProvider, because I believe its overkill if a simpler solution is available. Also, only this application has access to the database.
Any suggestions on how this can be fixed?
When a database is accessed by multiple connections, and one of the processes modifies the database, the SQLite database is locked until that transaction is committed. The timeout parameter specifies how long the connection should wait for the lock to go away until raising an exception.
There's no use checking before (if that is possible), it still can get locked between the check and your next call. Better would be to make your call, and handle possible exceptions, eg. retry a number of times and report an error after too much retries.
After doing some effort I did it (My app was working on perfect till android 2.3 but got db lock error when I used to run it on HoneyComb tablet).
I did using Semaphores (using lock in critical sections).
Example 1
public class DbExp extends SQLiteOpenHelper{
public static String Lock = "dblock";
private static final String DATABASE_NAME = "db.db";
private static final String TABLE_NAME = "table_name";
public void delete(Context mContext){
synchronized(Lock) {
SQLiteDatabase db = getWritableDatabase();
db.delete(TABLE_NAME, null, null);
db.close();
}
}
public void insert(){
synchronized(Lock) {
SQLiteDatabase db = getWritableDatabase();
db.insert(TABLE_NAME, ..., ...);
db.close();
}
}
}
Example 2
public class DB {
public static String Lock = "dblock";
private static final String DATABASE_NAME = "db.db";
private static final String TABLE_NAME = "table_name";
public void delete(Context mContext){
synchronized(Lock) {
SQLiteDatabase db = mContext.openOrCreateDatabase(DATABASE_NAME, Context.MODE_PRIVATE, null);
db.delete(TABLE_NAME, null, null);
db.close();
}
}
public void insert(Context mContext){
synchronized(Lock) {
SQLiteDatabase db = mContext.openOrCreateDatabase(DATABASE_NAME, Context.MODE_PRIVATE, null);
db.insert(TABLE_NAME, ..., ...);
db.close();
}
}
}
Hope this would help Anyone in future :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With