我想做的事
在我创建的应用中,我们正在保存需要加密的秘密用户数据。为此,我们要使用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)
答案 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)
对象。