解决sqlcipher从3.5.9升级到4.0.1引起的崩溃问题
由于客户对移动端的数据库有加密需求,并且最近要优化性能,所以升级了net.zetetic:android-database-sqlcipher库,但是却造成程序崩溃,异常如下:
Caused by: net.sqlcipher.database.SQLiteException: file is not a database: , while compiling: select count(*) from sqlite_master;
at net.sqlcipher.database.SQLiteCompiledSql.native_compile(Native Method)
at net.sqlcipher.database.SQLiteCompiledSql.compile(SQLiteCompiledSql.java:91)
at net.sqlcipher.database.SQLiteCompiledSql.<init>(SQLiteCompiledSql.java:64)
at net.sqlcipher.database.SQLiteProgram.<init>(SQLiteProgram.java:89)
at net.sqlcipher.database.SQLiteQuery.<init>(SQLiteQuery.java:48)
at net.sqlcipher.database.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:60)
at net.sqlcipher.database.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1954)
at net.sqlcipher.database.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1840)
at net.sqlcipher.database.SQLiteDatabase.keyDatabase(SQLiteDatabase.java:2571)
at net.sqlcipher.database.SQLiteDatabase.openDatabaseInternal(SQLiteDatabase.java:2502)
at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1204)
at net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1258)
at net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1253)
at net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1238)
at net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1274)
at org.penguin.project.sqlcipher.MainActivity.InitializeSQLCipher(MainActivity.java:34)
at org.penguin.project.sqlcipher.MainActivity.onCreate(MainActivity.java:18)
at android.app.Activity.performCreate(Activity.java:7436)
at android.app.Activity.performCreate(Activity.java:7426)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1286)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3279)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3484)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:86)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2123)
at android.os.Handler.dispatchMessage(Handler.java:109)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:7470)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:958)
经过研究发现,可以通过以下代码解决崩溃问题:
SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(databasePath, ZeteticApplication.DATABASE_PASSWORD, null, new SQLiteDatabaseHook() {
@Override
public void preKey(SQLiteDatabase database) {
}
@Override
public void postKey(SQLiteDatabase database) {
database.execSQL("PRAGMA cipher_page_size = 1024");
database.execSQL("PRAGMA kdf_iter = 64000");
database.execSQL("PRAGMA cipher_hmac_algorithm = HMAC_SHA1");
database.execSQL("PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1");
}
});
至于涉及到到greendao如何解决,明天再研究下,如果需要弄清楚参数的作用,请参考下面的网址:
https://www.zetetic.net/sqlcipher/sqlcipher-api/#key
另外提醒下,PRAGMA部分的语句必须放在postKey方法中执行,否则也会崩溃。