“code d'erreur 5: base de données est verrouillée” lors de l'utilisation d'un ContentProvider

J'ai une application qui s'exécute à une activité avec un service dans un processus distinct qui est commencé et lié à l'activité. Le service contient un gestionnaire qui publie un exécutable à exécuter après un certain délai.

Je veux que chaque composant pour se connecter à la base de données, j'ai donc mis en œuvre un fournisseur de contenu qui traite de l'accès à la base et je l'appelle à partir du service ou de l'activité via étendu AsyncTask sous-classes.

Tout cela fonctionne à merveille sur l'émulateur, mais quand je le lance il en debug sur mon téléphone je reçois un sporadiques de la base de données verrouillée erreur sur ma base de données écrit:

Mise à JOUR

J'ai apporté quelques modifications à ma base de données de la manipulation et de l'erreur a été légèrement modifié.

ERROR/Database(15235): Error inserting MY_MESSAGE
ERROR/Database(15235): android.database.sqlite.SQLiteException: error code 5: database is locked
ERROR/Database(15235):     at android.database.sqlite.SQLiteStatement.native_execute(Native Method)
ERROR/Database(15235):     at android.database.sqlite.SQLiteStatement.execute(SQLiteStatement.java:61)
ERROR/Database(15235):     at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1591)
ERROR/Database(15235):     at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1435)
ERROR/Database(15235):     at mypackagename.DatabaseHelper.insertLogging(DatabaseHelper.java:190)
ERROR/Database(15235):     at mypackagename.ContentProvider.insert(ContentProvider.java:139)
ERROR/Database(15235):     at android.content.ContentProvider$Transport.insert(ContentProvider.java:198)
ERROR/Database(15235):     at android.content.ContentResolver.insert(ContentResolver.java:604)
ERROR/Database(15235):     at mypackagename.Activity$LogToDatabase.doInBackground(Activity.java:642)
ERROR/Database(15235):     at mypackagename.Activity$LogToDatabase.doInBackground(Activity.java:1)
ERROR/Database(15235):     at android.os.AsyncTask$2.call(AsyncTask.java:185)
ERROR/Database(15235):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
ERROR/Database(15235):     at java.util.concurrent.FutureTask.run(FutureTask.java:138)
ERROR/Database(15235):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
ERROR/Database(15235):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
ERROR/Database(15235):     at java.lang.Thread.run(Thread.java:1019)

Je n'ai pas mis beaucoup de détails avant parce que je pensais que c'était un problème avec les différents processus ou threads, mais maintenant, je pense que le problème est plus susceptibles de se trouver dans le code de l'appel de la base de données.

Questions:

1) Pourquoi suis-je frapper les serrures quand je suis à l'aide d'un ContentProvider?

2) Pourquoi n'est-ce pas apparaître sur un équivalent de l'API 2.3.3 émulateur?

3) le fait qu'aucun de mes code intercepte une exception dire que l'erreur a été traitée correctement et je peux l'ignorer?

4) j'ai lu dans un autre endroit de quelqu'un ce qui suggère réglage du délai d'occupation.. Comment dois-je procéder?

L'ironie que c'est mon journalisation de débogage qui est la cause de l'erreur n'est pas perdu sur moi.

Si je ne peux pas le résoudre, ma prochaine étape est de regrouper les messages de journalisation dans une liste et de les jeter dans des lots de dix à la fois.

Voici le chemin à travers le code de l'erreur:

Activité:

private void logDatabaseMessage(String status, String message)
{
String[] args = {status, message};
LogToDatabase logTask = new LogToDatabase();
logTask.execute(args);      
}
private class LogToDatabase extends AsyncTask<String, Integer, Void>
{
@Override
protected Void doInBackground(final String... args) 
{
try
{
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); 
String dateText = dateFormat.format(new Date());
ContentValues loggingValues = new ContentValues();
loggingValues.put(MyContentProvider.LOGGING_DATETIME, dateText);
loggingValues.put(MyContentProvider.LOGGING_STATUS, args[0]);
loggingValues.put(MyContentProvider.LOGGING_MESSAGE, args[1]);
getContentResolver().insert(MyContentProvider.LOGGING_CONTENT_URI, loggingValues);
}
catch (Exception ex)
{
Log.e(TAG, "LogToDatabase.doInBackground threw exception: " + ex.getMessage());
ex.printStackTrace();
}               
return null;
}
}

ContentProvider:

@Override
public Uri insert(Uri uri, ContentValues values) 
{
Uri _uri = null;
long rowID = 0;
try
{
switch (uriMatcher.match(uri))
{
case LOGGING:
rowID = dbHelper.insertLogging(values);
if (rowID == 0)
throw new SQLException("Failed to insert row into " + uri);
_uri = ContentUris.withAppendedId(LOGGING_CONTENT_URI, rowID);
break;
default: throw new SQLException("Failed to insert row into " + uri);
}
if (rowID != 0)
getContext().getContentResolver().notifyChange(_uri, null);    
}
catch (Exception ex)
{
Log.e(TAG, LogPrefix + "insert threw exception: " + ex.getMessage());
ex.printStackTrace();
}
return _uri;    
}

DatabaseHelper:

public long insertLogging(ContentValues values)
{
long rowID = 0;
try
{
rowID = db.insert(LOGGING_TABLE, null,  values);
}
catch (Exception ex)
{
Log.e(TAG, LogPrefix + "ERROR: Failed to insert into logging table: " + ex.getMessage());
ex.printStackTrace();
}
return rowID;
}
InformationsquelleAutor TomDestry | 2011-12-02