使用 ContentProvider 时出现“错误代码 5:数据库已锁定”

2023-11-24

我有一个应用程序,它在启动并绑定到该活动的单独进程中运行带有服务的活动。该服务包含一个处理程序,该处理程序发布一个可运行对象以在延迟后运行。

我希望每个组件都登录到数据库,因此我实现了一个处理数据库访问的内容提供程序,并通过扩展的 AsyncTask 子类从服务或活动中调用它。

这一切在模拟器上都运行得很好,但是当我在手机上调试运行它时,我在数据库写入时遇到偶发的数据库锁定错误:

UPDATE

我对数据库处理进行了一些更改,错误略有变化。

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

内容提供商:

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

数据库助手:

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

您是否可能使用多个 SQLiteDatabase(或者 SQLiteOpenHelper)实例访问数据库?

您只能与数据库建立一个连接,否则您将遇到所遇到的错误。

SQLiteDatabase本身是线程安全的,这样您就可以同时访问它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 ContentProvider 时出现“错误代码 5:数据库已锁定” 的相关文章

随机推荐

  • 在控制台中查看 TFS 变更集详细信息

    我正在使用 TFS 并且想要查看包含多个文件中的更改的变更集上的所有更改 在 GUI 中查看此内容效率不高 因为我必须打开每个文件 我想做的是告诉控制台上的 TFS 向我显示对变更集编号 777 中的所有文件的所有更改 是否有命令可以执行此
  • 如何输入最初为 None 但保证获得值的提示变量

    我有一个类变量 如下所示 class MyClass def init self self value MyOtherClass None None self initialize value def initialize value se
  • Scala 方法调用中括号的规则是什么?

    toList 不是一个将某些内容转换为 List 的方法吗 如果是的话为什么我不能使用括号呢 我一定在这里遗漏了一些更基本的东西 这是示例 val l Array 1 2 3 toList works fine val l Array 1
  • 如何让 mechanize 等待网页“完全”加载?

    我想抓取一些动态加载其组件的网页 该页面有一个加载脚本 在浏览器中输入 URL 后 3 5 秒我就可以看到完整的页面 问题是 当我打电话时br open URL 响应是 0 秒处的网页 3 5 秒后 HTML 我想要的 和结果之间存在差异b
  • 如何让椭圆闪烁?

    我正在尝试在 WPF 中制作自定义控件 我希望它能够模拟 LED 闪烁的行为 该控件有三种状态 开 关和闪烁 我知道如何通过后面的代码设置打开和关闭 但是这个 WPF 动画东西简直让我发疯 我无法让任何东西动画化 该计划是拥有一个称为状态的
  • Numpy 矩阵旋转任意度数

    我尝试找到一种方法 在包含 RGB 等三个波段但值大于 0 255 的矩阵上应用任意度数的矩阵旋转 这是我的数据示例 其形状为 100 100 3 847 5 877 886 821 5 856 5 898 850 883 969 5 88
  • 我可以显式导入 dom 类型吗?

    按照惯例 开发人员会在全球范围内包含全局 dom 类型并在全球范围内使用它们 compilerOptions lib dom 是否可以显式使用 dom 类型 就像是 import MessagePort HTMLElement from d
  • 如何在 Android 中阅读 pdf

    我想在android 中阅读PDF 文件 我将 PDF 文件放在 asset 文件夹中 我如何从那里读取 PDF 文件 PDF阅读器链接 我已经检查了上面的链接 但它对我不起作用 它给我一个错误 说找不到活动 我还想在WebView中打开P
  • 作为类成员的灵活数组

    海湾合作委员会 G 9 这段代码 class foo int bar 111 123 产生有关灵活数组的初始值设定项的错误 但这一个 class foo int bar 2 111 123 正常编译 有什么解决方法可以不计算我输入的值吗 与
  • Jackson - 动态抑制属性的序列化(写入)

    我正在尝试使用 Jackson 将 Tomcat jersey 中的 java 对象转换为 JSON 对象 并希望动态抑制某些属性的序列化 写入 我可以使用 JsonIgnore 但我想在运行时做出忽略决定 有任何想法吗 因此 作为下面的示
  • Spring Zuul API 网关,在同一请求中使用 Spring Session / Redis 进行身份验证和路由

    在过去的几天里 我一直在苦苦寻找如何做到这一点 最后决定承认失败并寻求帮助 拜托 我遵循 Dave Syer 博士关于 Angular 和 Spring Security 的教程 特别是 Zuul 代理作为 api 网关以及将 Spring
  • toString():用于调试还是用于人类?

    class Address private enum Component NUMBER STREET STATE COUNTRY private Map
  • 真正的随机C#生成器

    Random ran new Random byte tmp byte ran Next 10 这段代码有替代方案吗 它似乎没有完全随机的行为 发生这种情况的原因有多种 一个常见的问题是创建多个实例Random程序中的类 当使用Random
  • 无法从 Visual Studio 2015 连接到 mysql

    所以我已经花了大约 2 天的时间尝试解决这个问题 我已经在我的工作场所电脑上成功修复了这个问题 但无法让它在我的家庭电脑上工作 我读过十几篇 SO 文章和 Oracle 论坛文章等等 但它仍然不起作用 我有用于 Visual Studio
  • 可视化点云

    我在找到的视差图像上有来自 gpu reprojectImageTo3D 的 3D 点 我现在想显示这个点云 如何将找到的点云转换为OpenCV to sensor msgs PointCloud2 我不需要发布点云 这仅用于调试可视化 是
  • 访问令牌中缺少“aud”声明

    由于我未知的原因 aud 声明不存在于访问令牌中 尽管它存在于 id 令牌中 将访问令牌发送到 API 后 我收到以下错误 持有者未经过身份验证 失败消息 IDX10214 观众 验证失败 观众 空 不匹配 validationParame
  • Flutter 2:无法确定捆绑的 Java 版本

    我在 Windows 10 下使用 Android Studio 来运行 flutter 项目 但是我有这个警告我想修复 X Unable to determine bundled Java version Try updating or
  • 在javascript中将指数表示法小数位限制为4

    如何在 JavaScript 中使用这种类型的值将小数位限制为 4 e 是指数 因为我使用的是十个值的幂 toFixed 似乎不起作用 1 0531436913408342e 7 5 265718456704172e 7 8 4251495
  • CSS Flexbox 影响 Bootstrap 3 布局

    我正在尝试在 Bootstrap 3 中创建下面的布局 我可以实现 sm 下显示的布局 并且使用 Flexbox 我想将 div 1 和 2 交换为 xs 屏幕 问题是 当我将包含的 div 设置为 Flexbox 时 它会将 sm 布局上
  • 使用 ContentProvider 时出现“错误代码 5:数据库已锁定”

    我有一个应用程序 它在启动并绑定到该活动的单独进程中运行带有服务的活动 该服务包含一个处理程序 该处理程序发布一个可运行对象以在延迟后运行 我希望每个组件都登录到数据库 因此我实现了一个处理数据库访问的内容提供程序 并通过扩展的 Async