SQLCipher no puede abrir la base de datos después de apprestart

Lo que estoy tratando de hacer


En la aplicación que estoy creando, estamos guardando datos de usuario secretos que necesitan ser cifrados. Para eso nos gustaría usar SQLCipher. Lo hemos implementado como en la documentación.

Ahora estoy enfrentando el siguiente problema. Si creo la base de datos por primera vez puedo leer y escribir el db. Si reinicio la aplicación, no puedo leer la base de datos de nuevo y obtener toneladas de errores. ¿Qué estoy haciendo mal?

Aquí está el código de nuestro 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 } 

Y así es como lo instanciamos:

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

Y el 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) 

es posible que necesite la tabla ANDROID_METADATA con (clave, valor) = ('locale', YOUR LOCALE)

Parece que está abriendo la base de datos de nuevo cuando su app restart.I tuvo el mismo error, pero lo soluciono mediante la creación de una clase de ayuda que almacenar en caché la base de datos abierta anteriormente y sólo abrirlo si es realmente necesario como a continuación.

 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; } } 

Así que cuando reinicie la aplicación, vuelva a intentar llamar al método openDatabase ().

Esta línea me parece extraña:

 databaseFile.mkdir(); 

mkdir() crea una carpeta, por lo que está pasando una carpeta en lugar de un archivo a openOrCreateDatabase() .

También creo que no deberías llamar a openOrCreateDatabase() en el constructor de SQLiteOpenHelper. Se encarga de crear el archivo de base de datos automáticamente. A continuación, puede obtener el objeto SQLiteDatabase llamando por ejemplo SQLiteOpenHelper.getWritableDatabase(password) .

  • ¿Puede alguien explicarme el paso de compilación en la creación de un archivo binario sqlcipher?
  • Android usando SQLCipher - ¿cómo se puede descifrar?
  • Sqlcipher 'open' performance con cordova y Cordova-SQLitePlugin
  • SQLCipher para Android: icudt46l.zip realmente necesario?
  • GreenDAO con Sqlcipher Ejemplo de Integración
  • Android SQCipher ¿Necesito cerrar la base de datos?
  • Cómo almacenar la clave utilizada en SQLCipher para android
  • ¿Cómo empezar con SQLCipher para Android?
  • Android No se puede cifrar la base de datos utilizando sqlcipher usando greendao
  • CREATE TABLE android_metadata falló al volver a abrir sqlcipher DB
  • Integración ormlite-4.9 con sqlcipher-2.08
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.