2

在我的 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/andlibs/文件夹中有正确的文件,因为数据库大部分时间都可以正常工作。但是,每隔一段时间我就会看到这个错误。我现在已经在手机上看到过两次这种情况,并且一直是在数小时不活动后恢复应用程序之后(如果它从内存中清除,我会在数据库中检查用户的 oauth 令牌)。

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

4

1 回答 1

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 例程调用到调用 的 JNI 层sqlite3_open_v2,设置软堆限制并设置忙超时。SQLiteDatabase我建议在本地添加日志记录,以验证您在崩溃时尝试获取实例时传递的有效路径和非空密码。SQLiteDatabase.loadLibs(this);多次调用不应导致明显的性能影响,发生的大部分是System.loadLibrary(…)映射到的调用Runtime.getRuntime().loadLibrary(…),一旦加载了动态库,后续调用将被忽略。

于 2013-09-10T13:39:02.253 回答