Exception SQLite: la base de données est verrouillée

J'ai un problème avec ma base de données SQLite dans une application Android. Cela semble se produire de temps en temps et je ne peux pas le reproduire, mais c'est le rapport que l'Android Market donne.

Fondamentalement, j'ai d'abord une activité d'écran qui commence par vérifier si toutes les données nécessaires sont dans la base de données. Sinon, il installera les données dans un thread asynchrone et fermera la connexion db.

  • Android Manifest Restrict To Tablets
  • Faire un aperçu avant-gardiste
  • Comment afficher les contacts dans une liste dans Android pour Android api 11+
  • La fonction geocoder.getFromLocation lance l'exception "Extinction temporelle en attente de réponse du serveur"
  • YouTube API Android: YouTubePlayerFragment en cours de chargement
  • Valeurs EditText dans la gamme
  • Ensuite, et alors, l'activité principale peut commencer, ce qui ouvre et lit / écrit la base de données.

    Ce code est exécuté à partir de la méthode onCreate de l'activité de l'écran d'accueil:

    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(""); } 

    Le code pour le thread asynchrone est:

     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); } } 

    Ce sont des éléments importants de la classe WordDBAdapter, qui est également utilisé par l'activité principale:

     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(); } ... } 

    Je reçois les exceptions suivantes, qui sont similaires mais ont un message différent:

    Premier type de message d'erreur:

     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) 

    Deuxième type de message d'erreur:

     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) 

    J'aimerais vraiment ne pas avoir à créer un ContentProvider, car je crois qu'il s'agit d'une solution excessive si une solution plus simple est disponible. En outre, seule cette application a accès à la base de données.

    Des suggestions sur la façon dont cela peut être corrigé?

  • Migration d'eclipse + SVN vers Android Studio
  • Programmeur de début intéressé par Android - Dois-je commencer par Java?
  • Vue étendue de la liste setOnChildClickListener ne fonctionne pas
  • Java: Différents résultats lors du décodage de la base64 avec java.util.Base64 vs android.util.Base64
  • Comment faire pour que le téléphone Android soit un casque bluetooth?
  • Différence entre JSONObject et JSONArray
  • 7 Solutions collect form web for “Exception SQLite: la base de données est verrouillée”

    Après avoir fait un effort, je l'ai fait (Ma application fonctionnait parfaitement jusqu'à Android 2.3 mais a eu une erreur de verrou db lorsque j'avais l'habitude de l'exécuter sur la tablette HoneyComb).
    J'ai utilisé Semaphores (à l'aide de verrouillage dans les sections critiques).

    Exemple 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(); } } } 

    Exemple 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(); } } } 

    J'espère que cela aiderait quelqu'un à l'avenir 🙂

    Si votre utilisation de Fragments et cela se produit avec des changements d'orientation, c'est parce que vous avez deux instances du même Fragment et que les deux ont leur propre instance d'une classe d'aide de Db d'une certaine sorte. Pour le faire fonctionner, vous devez soit détruire votre fragment sur le changement d'orientation, soit le reconstruire, soit trouver un moyen de détruire la classe Db helper. Ce n'est que pour les fragments avec des problèmes d'orientation. J'ai dû faire beaucoup de dépannage pour le comprendre, donc j'espère que quelqu'un trouve cela utile

    C'était la raison pour moi:

    J'ai oublié de terminer la transaction dans mon appel de fonction après l'insertion dans db. Donc, lorsque j'ai essayé d'insérer un autre enregistrement d'une autre activité, j'ai une exception à la base de données verrouillée. L'ajout de l'énoncé ci-dessous a résolu mon problème.

     sqlDB.endTransaction(); 

    Je vous suggère de fermer votre DB dans le thread principal et de l'ouvrir et de le fermer dans votre méthode doInBackground:

      @Override protected Integer doInBackground(String... arg0) { db.open(); try { // your code here } finally { db.close() } return 1; } 

    De plus, vous ne devez pas appeler directement des méthodes d'interface utilisateur à partir d'AsyncTask, car l'interface utilisateur n'est pas sécurisée. Au lieu de cela, mettez la méthode UpdateProgress à partir de doInBackground et mettez à jour votre ProgressDialog de onProgressUpdate, car onProgressUpdate est appelé à partir du thread principal.

    On dirait que c'est une question plus ancienne, mais peut-être que cela aidera quelqu'un. J'avais le même problème, je demandais probablement autour d'une douzaine de tables dans une base de données et risquait régulièrement, pas toujours, mais parfois.

    Enfin, et ce peut être hackey, je viens de créer une base de données distincte pour chaque table. Donc maintenant j'ai une douzaine de bases de données, chacune avec une table. Mais, pas plus d'exceptions. Le code était un son, créait, ouvrait et se refermait correctement, semblait avoir des collisions quelque part.

    Comme je l'ai dit, vous pourriez considérer cela comme un hackey, mais cela a réglé mon problème.

    Db

    Peut-être que c'est parce que vous n'avez pas correctement ouvert ou créé la base de données. Essayez s'il en est ainsi.

     mDb = mCtx.openOrCreateDatabase(DatabaseName, SQLiteDatabase.CREATE_IF_NECESSARY, null); 

    Dans la classe DatabaseHelper:

     public DatabaseHelper(Context aContext) { mDb = aContext.openOrCreateDatabase(DatabaseName, SQLiteDatabase.CREATE_IF_NECESSARY, null); OpenHelper openHelper = new OpenHelper(aContext, mDb ); mDb = openHelper.getWritableDatabase(); } 

    Ces lignes de code ont résolu mon (le même) problème:

    (J'ai eu ma transaction ouverte avant …)

     writableDatabase.endTransaction(); writableDatabase.close(); dbHelper.close(); 
    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.