【问题标题】:Android SQLiteException: Failed to change locale for db to 'en_US'Android SQLiteException:无法将 db 的语言环境更改为“en_US”
【发布时间】:2013-01-31 17:09:33
【问题描述】:

我最近更新了我的一个(开源)Android 应用程序,但我的用户遇到了我无法复制的异常。关键部分是:

android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5)

然后

Caused by: android.database.sqlite.SQLiteException: Failed to change locale for db '/data/data/com.airlocksoftware.hackernews/databases/hacker_news_cache.db' to 'en_US'.

这发生在运行 Android 2.3 - 4.2.1 的设备上,以及我尝试连接到数据库的应用程序中的多个位置。使用后我将关闭数据库。

我找不到有关“无法更改 db 语言环境”异常的更多信息。当我查看source for SQLiteConnection (line 386) 时,这似乎是“android_metadata”表或“使用新语言环境更新索引”的问题。

Here is the code that's causing the exception (on Github).

java.lang.RuntimeException: An error occured while executing doInBackground()
at android.support.v4.content.ModernAsyncTask$3.done(ModernAsyncTask.java:137)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
at java.util.concurrent.FutureTask.run(FutureTask.java:239)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
at java.lang.Thread.run(Thread.java:856) Caused by: android.database.sqlite.SQLiteException: Failed to change locale for db '/data/data/com.airlocksoftware.hackernews/databases/hacker_news_cache.db' to 'en_US'.
at android.database.sqlite.SQLiteConnection.setLocaleFromConfiguration(SQLiteConnection.java:386)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:218)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:854)
at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:229)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
at com.airlocksoftware.database.DbInterface.(DbInterface.java:28)
at com.airlocksoftware.hackernews.loader.StoryLoader.loadStories(StoryLoader.java:62)
at com.airlocksoftware.hackernews.loader.StoryLoader.loadInBackground(StoryLoader.java:54)
at com.airlocksoftware.hackernews.loader.StoryLoader.loadInBackground(StoryLoader.java:1)
at android.support.v4.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:240)
at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:51)
at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:40)
at android.support.v4.content.ModernAsyncTask$2.call(ModernAsyncTask.java:123)
at java.util.concurrent.FutureTask.run(FutureTask.java:234)
... 3 more Caused by: android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5)
at android.database.sqlite.SQLiteConnection.nativeExecute(Native Method)
at android.database.sqlite.SQLiteConnection.execute(SQLiteConnection.java:548)
at android.database.sqlite.SQLiteConnection.setLocaleFromConfiguration(SQLiteConnection.java:364)
... 24 more

【问题讨论】:

  • 我遇到了完全相同的问题,而且只是在少数设备之一上。它不依赖于设备上设置的区域设置,无论设置哪个都抛出异常。您是否从 AsyncTask 访问数据库?您是否在一个 SQLiteDatabase 对象中有两个或多个表(您可能同时访问)?
  • @anoniim 我正在从加载程序访问数据库,所以是的,它是在另一个线程上完成的。此特定代码应该只访问一个表,但可能有其他线程同时访问其他表。你认为这是问题所在吗?
  • 请显示CacheDbOpener的来源?
  • @t0mm13b Here's the source for CacheDbOpener
  • 我猜,您在AsyncLoader 中使用getContext(),最好尝试在范围之外使用静态Context,即在应用程序级别或活动级别声明,并且例如,在调用CacheDbOpener(static_Context) 时使用它,看看会得到什么结果?

标签: android sqlite sqliteopenhelper


【解决方案1】:

检查您的数据库内容,特别是“android_metadata”。这是一个带有这个 DDL 的表:

CREATE TABLE android_metadata ( 
    locale TEXT 
);

其中应包含至少一条具有此内容的记录:

en_US

这解决了我自己的问题。

更多详情:
使用诸如SQLiteStudio 之类的 sqlite 编辑器打开您的数据库文件,然后打开 android_metadata 表(如果它不存在,请创建它。(您可以使用查询编辑器(工具>打开查询编辑器)创建它)和复制/粘贴上面的 DDL 代码)

为了插入记录,您可以在查询编辑器中复制/粘贴这一行:

insert into android_metadata values ('en_us');

提示:要在 SQLiteStudio 中运行查询,您应该按下工具栏中带有 图标的按钮。

【讨论】:

  • 您能解释一下您的答案吗?请添加更多详细信息,您是如何为 en_US 提供内容的??
  • 感谢更新,但我使用的是 Eclipse。我还需要为 en-us 创建包含我的新表吗(我需要为 en-us 再次创建的表)?
  • Eclipse 与 sqlite 数据库无关。你不能有两个同名的表!因此,如果您已经有这样的表,只需使用 SQLiteStudio 运行“插入”查询。
【解决方案2】:

密钥是android.database.sqlite.SQLiteDatabaseLockedException

我遇到了同样的问题,并且随着数据库锁定的增加而不断增加。

怎么办? - 消除数据库锁定。

怎么做? - 确保没有并发的写调用发生,并且

您可以阅读有关避免数据库锁定的更多信息 here 并在此很好地解释 SO answer

我建议将所有写调用转移到一个线程上,这样可以避免锁定。您可以为此使用AsyncQueryHandler

【讨论】:

    【解决方案3】:

    这并不能完全回答问题,但您可能还想查看这篇文章,看看是否可以将其添加到您的 DbHelperSingleton 中,因为这似乎与您面临的错误相同:

    Failed to change locale for db '/data/data/my.easymedi.controller/databases/EasyMediInfo.db' to 'en_US'

    【讨论】:

    • SQLiteOpenHelper 包装调用以直接打开数据库。这个 SO 答案建议修改该调用,但 SQLiteOpenHelper 不是 OP 编写的代码。
    【解决方案4】:

    如果您要更改应用程序中的区域设置,请确保在打开数据库之前进行更改。

    我在打开数据库后切换区域设置时在我的应用程序中遇到了同样的问题,并且它试图根据不存在的区域设置切换到不同的数据库。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-15
      • 2021-08-06
      • 1970-01-01
      • 2018-01-24
      • 1970-01-01
      相关资源
      最近更新 更多