【问题标题】:net.sqlcipher.database.SQLiteException while opening database after resuming app恢复应用程序后打开数据库时出现 net.sqlcipher.database.SQLiteException
【发布时间】:2013-09-10 03:17:54
【问题描述】:

在我的 Android 应用程序中使用加密的 SQLCipher 数据库时出现以下错误,但只能关闭和打开:

net.sqlcipher.database.SQLiteException: not an error
    at net.sqlcipher.database.SQLiteDatabase.dbopen(Native Method)
    at net.sqlcipher.database.SQLiteDatabase.<init>(SQLiteDatabase.java:1950)
    at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:900)
    at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:947)
    at net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:195)
    at com.android.storage.DatabaseHelper.getReadable(DatabaseHelper.java:99)
    ...

我在assets/libs/ 文件夹中有正确的文件,因为数据库大部分时间都运行良好。但是,每隔一段时间我就会看到这个错误。我现在已经在手机上看到过两次这种情况,并且总是在数小时不活动后恢复应用程序之后(如果它从内存中清除,我会在数据库中检查用户的 oauth 令牌)。

我只从 Application::onCreate() 方法调用“SQLiteDatabase.loadLibs(this)”,所以我的直觉是它不会在简历中被调用,而是抛出错误。 这听起来可能吗? 如果可以,我应该在哪里调用 loadLibs?用户可以在任何活动中输入应用程序,如果令牌不在内存中,我可以访问数据库。我将我的选项视为在每个 Activity::onCreate 上调用 loadLibs 或在每次尝试打开数据库时调用它。 如果我这样多次调用它会不会造成任何伤害或性能问题?

【问题讨论】:

  • 这是您用于 SQLiteDatabase 的外部库吗?因为默认导入是 android.database.sqlite.SQLiteDatabase;
  • 是的,我正在使用加密的SQLCipher 数据库。我已经更新了问题以明确这一点。
  • 确实很奇怪。我遇到过同样的问题。我会尝试建议的解决方案,希望不会对性能产生任何影响

标签: android sqlite sqlcipher


【解决方案1】:

您可以考虑将SQLiteDatabase.loadLibs(this); 移至net.sqlcipher.database.SQLiteOpenHelper 的应用程序子类。然后,您可以将 Application 子类的静态实例作为其参数传递。以下内容可能是一个示例:

public class SchemaManager extends net.sqlcipher.database.SQLiteOpenHelper {

  private static SchemaManager instance;

  public static synchronized SchemaManager getInstance() {
    if(instance == null) {
      SQLiteDatabase.loadLibs(YourApplication.getInstance());
      instance = new SchemaManager(…)
    }
    return instance;
  }
}

关于提供的异常,Java 例程调用到调用sqlite3_open_v2 的 JNI 层,设置软堆限制并设置繁忙超时。我建议在本地添加日志记录以验证您在崩溃时尝试获取 SQLiteDatabase 实例时传递的有效路径和非空密码。多次调用SQLiteDatabase.loadLibs(this); 不会对性能造成明显影响,发生的大部分情况是对System.loadLibrary(…) 的调用,这些调用会映射到Runtime.getRuntime().loadLibrary(…),一旦加载了动态库,后续调用将被忽略。

【讨论】:

  • 自从进行此更改后,我还没有看到此问题。谢谢尼克。
  • 嗨尼克,即使我们尝试以静态方式加载库,我们仍然会遇到这个问题。几乎相同的错误(我可以说相同,因为堆栈跟踪也相同)。调用 getReadableDatabse() 或 getWritableDatabase() 是由多个线程进行的,我们尝试将“同步”添加到 getReadableDatabase() 和 getWritableDatabase() 函数中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-12
  • 1970-01-01
  • 2010-11-12
相关资源
最近更新 更多