SQLCipher后可以AP preSTART无法打开数据库无法打开、数据库、SQLCipher、AP

2023-09-07 08:49:21 作者:劳资会发电

我想做什么

在应用程序我创建我们节省了需要被加密的机密用户数据。为此,我们想用SQLCipher。我们已经实现了文档。

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

SQLCipher下载 SQLCipher官方免费下载

下面是我们SQLiteOpenHeler的code:

 公共数据库(上下文CTX){
        超(CTX,DATABASE_NAME,空,DATABASE_VERSION);

        尝试{
            mKeySaver =新KeySaver(CTX);
            文件databaseFile = ctx.getDatabasePath(Database.DATABASE_NAME);

            如果(databaseFile.exists()){
                SQLiteDatabaseHook挂钩=新SQLiteDatabaseHook(){
                    公共无效pre键(SQLiteDatabase数据库){
                        database.rawExecSQL(杂kdf_iter = 5000);
                    }
                    公共无效postKey(SQLiteDatabase数据库){}
                };
                MDB = SQLiteDatabase.openOrCreateDatabase(databaseFile,mKeySaver.getKey(),空,钩);

            } 其他 {
                databaseFile.mkdir();
                MDB = SQLiteDatabase.openOrCreateDatabase(databaseFile,mKeySaver.getKey(),NULL);
                mDb.setLocale(Locale.GERMAN);
            }

        }赶上(例外五){
            Log.d(数据库,异常+ E);
        }
    }


    @覆盖
    公共无效的onCreate(SQLiteDatabase sqLiteDatabase){
        尝试{
            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);
        }赶上(例外五){
            Log.e(数据库,异常+ E);
        }

    }

    @覆盖
    公共无效onUpgrade(SQLiteDatabase sqLiteDatabase,诠释oldVersion,诠释静态网页){
        如果(oldVersion> =静态网页){
            返回;
        }

        //瀑布EIN DB-更新stattfinden sollte code得票数

    }
 

这就是我们如何将它实例:

  SQLiteDatabase.loadLibs(mContext.getApplicationContext());
mKeySaver =新KeySaver(mContext);
MDB =新的数据库(mContext.getApplicationContext());
DB_PASSWORD = mKeySaver.getKey();
mDatabase = mDb.getWritableDatabase(DB_PASSWORD);
 

而Logcatdump:

  9月4号至23号:00:44.723 2405至2405年/ IVO E /数据库:CREATE TABLE android_metadata失败
九月四日至23日:00:44.726二四零五年至2405年/ IVO E /数据库:无法setlocale()的施工时,关闭数据库
    net.sqlcipher.database.SQLiteException:文件是加密的或不是一个数据库
            在net.sqlcipher.database.SQLiteDatabase.native_setLocale(本机方法)
            在net.sqlcipher.database.SQLiteDatabase.setLocale(SQLiteDatabase.java:2092)
            在net.sqlcipher.database.SQLiteDatabase< INIT>(SQLiteDatabase.java:1958)
            在net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:875)
            在net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:907)
            在net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:132)
            在net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:197)
            在net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:184)
            在ivo.database.adapter.AccountAdapter.checkAccountPassword(AccountAdapter.java:79)
            在ivo.activity.LoginActivity.attemptLogin(LoginActivity.java:168)
            在ivo.activity.LoginActivity $ 2.onClick(LoginActivity.java:88)
            在android.view.View.performClick(View.java:4756)
            在android.view.View $ PerformClick.run(View.java:19748)
            在android.os.Handler.handleCallback(Handler.java:739)
            在android.os.Handler.dispatchMessage(Handler.java:95)
            在android.os.Looper.loop(Looper.java:135)
            在android.app.ActivityThread.main(ActivityThread.java:5254)
            在java.lang.reflect.Method.invoke(本机方法)
            在java.lang.reflect.Method.invoke(Method.java:372)
            在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:898)
            在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:693)
九月四日至23日:00:44.730二四零五年至2405年/ swisscom.ivocore E / SQLiteOpenHelper:无法打开ivo.db写(会尝试只读):
    net.sqlcipher.database.SQLiteException:文件是加密的或不是一个数据库
            在net.sqlcipher.database.SQLiteDatabase.native_setLocale(本机方法)
            在net.sqlcipher.database.SQLiteDatabase.setLocale(SQLiteDatabase.java:2092)
            在net.sqlcipher.database.SQLiteDatabase< INIT>(SQLiteDatabase.java:1958)
            在net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:875)
            在net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:907)
            在net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:132)
            在net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:197)
            在net.sqlcipher.database.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:184)
            在ivo.database.adapter.AccountAdapter.checkAccountPassword(AccountAdapter.java:79)
            在ivo.activity.LoginActivity.attemptLogin(LoginActivity.java:168)
            在ivo.activity.LoginActivity $ 2.onClick(LoginActivity.java:88)
            在android.view.View.performClick(View.java:4756)
            在android.view.View $ PerformClick.run(View.java:19748)
            在android.os.Handler.handleCallback(Handler.java:739)
            在android.os.Handler.dispatchMessage(Handler.java:95)
            在android.os.Looper.loop(Looper.java:135)
            在android.app.ActivityThread.main(ActivityThread.java:5254)
            在java.lang.reflect.Method.invoke(本机方法)
            在java.lang.reflect.Method.invoke(Method.java:372)
            在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:898)
            在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:693)
 

解决方案

这行看起来怪我:

  databaseFile.mkdir();
 

的mkdir()创建一个文件夹,因此你传递一个文件夹,而不是一个文件, openOrCreateDatabase()

另外,我想你不应该叫 openOrCreateDatabase()在SQLiteOpenHelper的构造。它需要自动创建数据库文件的照顾。然后,你可以通过调用例如让 SQLiteDatabase 对象 SQLiteOpenHelper.getWritableDatabase(密码)

What I'm trying to do

In the app I'm creating we're saving secret user data that needs to be encrypted. For that we'd like to use SQLCipher. We've implemented as in the documentation.

Now I'm facing following problem. If I create the database for the first time I can read and write the db. If I restart the app I'm unable to read the database again and get tons of errors. What am I doing wrong?

Here's the Code of our 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

    }

And that's how we instantiate it:

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

And the 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)

解决方案

This line looks weird to me:

databaseFile.mkdir();

mkdir() creates a folder, hence you are passing a folder instead of a file to openOrCreateDatabase().

Also I think you shouldn't call openOrCreateDatabase() in the SQLiteOpenHelper's constructor. It takes care of creating the database file automatically. Then you can get the SQLiteDatabase object by calling for example SQLiteOpenHelper.getWritableDatabase(password).