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.
- Estoy usando SQLCIPHER para leer o escribir la base de datos que consigue el error
- Uso de DBFlow, ¿cómo cifrar una base de datos ya existente?
- Manera correcta de almacenar la clave de cifrado para la base de datos SqlCipher
- SQLCipher - Abrir una base de datos cifrada en el escritorio
- Android Proguard SqlCipher NoClassDefFoundError
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)
- Net.sqlcipher.database.SQLiteException: no es un error:
- ¿Cómo puedo usar ORMLite con SQLCipher juntos en Android?
- ¿SQLCipher permite acceder a la base de datos por otra aplicación (si DB en SD-CARD)
- Cifrar la base de datos sqlite Android:
- Usando SQLCipher con el archivo de base de datos SQLite enviado sqlite
- Archivo está encriptado o no es una base de datos (excepción net.sqlcipher.database.SQLiteException)
- SQL Cursor lanza fuera de la memoria mientras llama a getString
- Android Studio (Beta v0.8.6) e integración con SQLCipher (v3.1.0)
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)
.
- LibGdx Gdx-Pay extensión obtener el precio del artículo
- Realm para ARM64 en v0.79 + hace que otras bibliotecas nativas no se encuentren en un Galaxy S6