У меня есть приложение, которое запускает действие со службой в отдельном процессе, который запускается и привязывается к действию.Служба содержит обработчик, который отправляет исполняемый файл для запуска после задержки.
Я хочу, чтобы каждый компонент регистрировался в базе данных, поэтому я реализовал поставщика контента, который имеет дело с доступом к базе данных, и я вызываю его из службыили действия через расширенные подклассы AsyncTask.
Все это прекрасно работает на эмуляторе, но когда я запускаю его в режиме отладки на своем телефоне, я получаю случайную ошибку блокировки базы данных при записи в базу данных:
ОБНОВЛЕНИЕ
Я внес некоторые изменения в обработку своей базы данных, и ошибка немного изменилась.
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)
Я не помещал много деталей раньше, потому что я думалэто была проблема с различными процессами или потоками, но теперь я думаю, что проблема, скорее всего, находится в коде, вызывающем базу данных.
Вопросы:
1) Почему я использую блокировки при использовании ContentProvider?
2) Почему это не отображается на эквивалентном эмуляторе API 2.3.3?
3) Означает ли тот факт, что ни один из моего кода не улавливает исключение, означает, что ошибка была обработана правильно, и я могу ее игнорировать?
4) Я читал в другом месте, кто-то предложил изменить время ожидания.Как бы я это сделал?
Ирония в том, что именно моя отладочная запись вызывает ошибку, не теряется на мне.
Если я не могу ее решить, мой следующий шаг - объединить сообщения регистрации в списке.и выгрузить их по десять штук за раз.
Вот путь к коду ошибки:
Активность:
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;
}