SQLite exception: Database is locked issue
android, exception, locking, sqlite
Solution
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 :)
Problem
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?