我在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/
文件夹中有正确的文件,因为数据库大部分时间都能正常运行。但是,每隔一段时间我就会看到这个错误。我现在已经在手机上看到了这两次,并且在经过数小时不活动后恢复应用程序之后一直都是这样(如果从内存中清除了用户在db中的oauth令牌)。
我只从Application :: onCreate()方法调用“SQLiteDatabase.loadLibs(this)”,所以我的预感是这不是在简历上调用而是抛出错误。 这听起来有可能吗?如果是这样,我应该在哪里调用loadLibs?用户可以在任何活动中输入应用程序,如果令牌不在内存中,我将访问数据库。我看到我的选项是在每个Activity :: onCreate上调用loadLibs,或者每当我尝试打开db时调用它。 如果我这样多次调用它会导致任何伤害或性能问题吗?
答案 0 :(得分: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(…)
的调用。忽略。