在apprestart之后,SQLCipher无法打开数据库

时间:2015-04-23 07:11:37

标签: android database android-5.0-lollipop sqlcipher

我想做的事

在我创建的应用中,我们正在保存需要加密的秘密用户数据。为此,我们要使用SQLCipher。我们已经在文档中实现了。

现在我面临以下问题。如果我是第一次创建数据库,我可以读取和写入数据库。如果我重新启动应用程序,我将无法再次读取数据库并收到大量错误。我做错了什么?

这是我们的SQLiteOpenHeler代码:

public Database (Context ctx){
        super(ctx, DATABASE_NAME, null, DATABASE_VERSION);

        try{
            mKeySaver = new KeySaver(ctx);
            File databaseFile = ctx.getDatabasePath(Database.DATABASE_NAME);

            if(databaseFile.exists()){
                SQLiteDatabaseHook hook = new SQLiteDatabaseHook(){
                    public void preKey(SQLiteDatabase database){
                        database.rawExecSQL("PRAGMA kdf_iter = 5000");
                    }
                    public void postKey(SQLiteDatabase database){}
                };
                mDb = SQLiteDatabase.openOrCreateDatabase(databaseFile, mKeySaver.getKey(), null, hook);

            } else {
                databaseFile.mkdir();
                mDb = SQLiteDatabase.openOrCreateDatabase(databaseFile, mKeySaver.getKey(), null);
                mDb.setLocale(Locale.GERMAN);
            }

        } catch (Exception e){
            Log.d("Database", "Exception " + e);
        }
    }


    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        try{
            sqLiteDatabase.execSQL(CREATE_TABLE_ACCOUNT);
            sqLiteDatabase.execSQL(CREATE_TABLE_ASSIGNMENT_DETAILS);
            sqLiteDatabase.execSQL(CREATE_TABLE_ASSIGNMENT_OVERVIEW);
            sqLiteDatabase.execSQL(CREATE_TABLE_ASSIGNMENT_UPLOAD);
            sqLiteDatabase.execSQL(CREATE_TABLE_ASSIGNMENT_USER);
            sqLiteDatabase.execSQL(CREATE_TABLE_ACCOUNT);
        }catch (Exception e){
            Log.e("Database", "Exception " + e);
        }

    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
        if (oldVersion >= newVersion) {
            return;
        }

        // Falls ein DB-Update stattfinden sollte Code hier

    }

以及我们如何实例化它:

SQLiteDatabase.loadLibs(mContext.getApplicationContext());
mKeySaver = new KeySaver(mContext);
mDb = new Database(mContext.getApplicationContext());
db_password = mKeySaver.getKey();
mDatabase = mDb.getWritableDatabase(db_password);

和Logcatdump:

04-23 09:00:44.723    2405-2405/ivo E/Database﹕ CREATE TABLE android_metadata failed
04-23 09:00:44.726    2405-2405/ivo E/Database﹕ Failed to setLocale() when constructing, closing the database
    net.sqlcipher.database.SQLiteException: file is encrypted or is not a database
            at net.sqlcipher.database.SQLiteDatabase.native_setLocale(Native Method)
            at net.sqlcipher.database.SQLiteDatabase.setLocale(SQLiteDatabase.java:2092)
            at net.sqlcipher.database.SQLiteDatabase.<init>(SQLiteDatabase.java:1958)
            at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:875)
            at net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:907)
            at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:132)
            at net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:197)
            at net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:184)
            at ivo.database.adapter.AccountAdapter.checkAccountPassword(AccountAdapter.java:79)
            at ivo.activity.LoginActivity.attemptLogin(LoginActivity.java:168)
            at ivo.activity.LoginActivity$2.onClick(LoginActivity.java:88)
            at android.view.View.performClick(View.java:4756)
            at android.view.View$PerformClick.run(View.java:19748)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5254)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:898)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:693)
04-23 09:00:44.730    2405-2405/swisscom.ivocore E/SQLiteOpenHelper﹕ Couldn't open ivo.db for writing (will try read-only):
    net.sqlcipher.database.SQLiteException: file is encrypted or is not a database
            at net.sqlcipher.database.SQLiteDatabase.native_setLocale(Native Method)
            at net.sqlcipher.database.SQLiteDatabase.setLocale(SQLiteDatabase.java:2092)
            at net.sqlcipher.database.SQLiteDatabase.<init>(SQLiteDatabase.java:1958)
            at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:875)
            at net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:907)
            at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:132)
            at net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:197)
            at net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:184)
            at ivo.database.adapter.AccountAdapter.checkAccountPassword(AccountAdapter.java:79)
            at ivo.activity.LoginActivity.attemptLogin(LoginActivity.java:168)
            at ivo.activity.LoginActivity$2.onClick(LoginActivity.java:88)
            at android.view.View.performClick(View.java:4756)
            at android.view.View$PerformClick.run(View.java:19748)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5254)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:898)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:693)

3 个答案:

答案 0 :(得分:0)

您可能需要使用表格ANDROID_METADATA,其中包含(键,值)=(&#39;区域设置&#39;,您的位置)

答案 1 :(得分:0)

当你的应用程序重新启动时,看起来你正在再次打开数据库。我有同样的错误,但我通过创建一个缓存先前打开的数据库的帮助程序类来解决它,只有在真正需要时才打开它。如下所示。 / p>

public class Helper {

    private static net.sqlcipher.database.SQLiteDatabase database;

    public static net.sqlcipher.database.SQLiteDatabase openDatabase(Context context, String databaseName, String password) {
        if (database == null) {
            database = net.sqlcipher.database.SQLiteDatabase .openOrCreateDatabase(context.getDatabasePath(context.getResources().getString(database)), password, null);
         }

        return database;
    }
}

因此,当您的应用重新启动时,请尝试再次调用openDatabase()方法。

答案 2 :(得分:0)

这条线对我来说很奇怪:

databaseFile.mkdir();

mkdir()创建一个文件夹,因此您将文件夹而不是文件传递给openOrCreateDatabase()

另外我认为你不应该在SQLiteOpenHelper的构造函数中调用openOrCreateDatabase()。它负责自动创建数据库文件。然后,您可以通过调用示例SQLiteDatabase来获取SQLiteOpenHelper.getWritableDatabase(password)对象。