Another issue migrating to new sqlcipher in android

HI,
I wrote an android sqlcipher app about 10 years ago. Now I am required
to migrate to the new 4 schema. In my attempt, I supply the old DB (named SOSdata.db)
in assets. When this new app now runs for the first time, it copies the old
DB from assets, and them attempts to migrate it to the current schema.

Can’t seem to get it to work. Am using community version of sqlcipher.
Also, I kinda don’t know what I am doing.

… would really appreciate some help on this. Thanks

Here is the code snippet that encounters a problem. The state at the beginning
of the snippet is that the old DB has been copied from assets to the app
storage and oldDB has been set to true.


File odbFile = new File(dbpath);
if( odbFile.exists() ) {
Log.v(TAG, "(HelloSQL) onResume: odbFile exists at " + dbpath);
}

System.loadLibrary(“sqlcipher”);
if( oldDB ) {
hook = new SQLiteDatabaseHook() {
public void preKey(SQLiteConnection connection) {}
public void postKey(SQLiteConnection connection) {
connection.executeForString(“PRAGMA cipher_migrate”,new Object{}, null );
}
};
} else {
hook = new SQLiteDatabaseHook() {
public void preKey(SQLiteConnection connection) {}
public void postKey(SQLiteConnection connection) {}
};
}

try {
SQLiteDatabase database = SQLiteDatabase.openDatabase(dbpath, “password”, null, 0, hook);
Log.v(TAG, "(HelloSQL) conResume: opened SQL database. " );
}
catch(Exception e) {
Log.v(TAG, "(HelloSQL): onResume: exception " + e );
Log.v(TAG, "(HelloSQL) conResume: leave, failed to open V3 database. " );
}

Here is what I see from Logcat in Android Studio:

V (HelloSQL) onResume: enter
V (HelloSQL) copyOldDBfromAssets: enter
V (HelloSQL) copyOldDBfromAssets: initial database size = 48128
V (HelloSQL) copyOldDBfromAssets: leave, success.
V (HelloSQL) onResume: odbFile exists at /data/data/com.demo.hellosql/SOSdata.db
I Database keying operation returned:0
E (26) statement aborts at 2: [PRAGMA user_version;] file is not a database
E (14) cannot open file at line 44576 of [8653b75887]
E (14) os_unix.c:44576: (2) open(/data/data/com.demo.hellosql/SOSdata.db-migrated) -
E (14) statement aborts at 4: [ATTACH DATABASE ‘/data/data/com.demo.hellosql/SOSdata.db-migrated’ as migrate;] unable to open database: /data/data/com.demo.hellosql/SOSdata.db-migrated
W JNI critical lock held for 300.354ms on Thread[1,tid=23422,Runnable,Thread*=0xb4000071b6e92010,peer=0x7203fe48,“main”]
E (14) unable to open database file in "SELECT COUNT() FROM sqlite_schema;"
E Failed to open database ‘/data/data/com.demo.hellosql/SOSdata.db’.
android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file (code 14): , while compiling: SELECT COUNT(
) FROM sqlite_schema;
at net.zetetic.database.sqlcipher.SQLiteConnection.nativePrepareStatement(Native Method)
at net.zetetic.database.sqlcipher.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:973)
at net.zetetic.database.sqlcipher.SQLiteConnection.executeForLong(SQLiteConnection.java:628)
at net.zetetic.database.sqlcipher.SQLiteConnection.open(SQLiteConnection.java:240)
at net.zetetic.database.sqlcipher.SQLiteConnection.open(SQLiteConnection.java:203)
at net.zetetic.database.sqlcipher.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:475)
at net.zetetic.database.sqlcipher.SQLiteConnectionPool.open(SQLiteConnectionPool.java:189)
at net.zetetic.database.sqlcipher.SQLiteConnectionPool.open(SQLiteConnectionPool.java:181)
at net.zetetic.database.sqlcipher.SQLiteDatabase.openInner(SQLiteDatabase.java:1028)
at net.zetetic.database.sqlcipher.SQLiteDatabase.open(SQLiteDatabase.java:1013)
at net.zetetic.database.sqlcipher.SQLiteDatabase.openDatabase(SQLiteDatabase.java:840)
at net.zetetic.database.sqlcipher.SQLiteDatabase.openDatabase(SQLiteDatabase.java:740)
at com.demo.hellosql.HelloSQL.onResume(HelloSQL.java:101)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1666)
at android.app.Activity.performResume(Activity.java:8915)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:5166)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:5209)
at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:57)
at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:60)
at android.app.servertransaction.TransactionExecutor.executeLifecycleItem(TransactionExecutor.java:254)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:228)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:91)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2544)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loopOnce(Looper.java:232)
at android.os.Looper.loop(Looper.java:317)
at android.app.ActivityThread.main(ActivityThread.java:8501)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:878)
V (HelloSQL): onResume: exception android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file (code 14): , while compiling: SELECT COUNT(*) FROM sqlite_schema;
V (HelloSQL) conResume: leave, failed to open V3 database.
V (HelloSQL) onResume: leave

Hi @jbsalis,

It appears your database path is the root of the application, not within the databases directory. I noticed you’re receiving an SQLiteCantOpenDatabaseException, does it behave the same way if you extract your database file into the databases directory and attempt to migrate it?

If the error persists, what happens when you open the database file on your host computer and use the SQLCipher command line shell to attempt an upgrade outside of Android?

Thanks for your suggestion. I had originally put the db under /databases directory, and got the same result. My host computer is windows… I will look for a sqlcipher binary for windows. Did not know that was a possibility. will post an update when I learn something.

I found a sqlcipher windows binary at Katecca/sqlcipher-static-binary on github… but I have no documentation on how to run it. Is that the program you recommended to try on Windows?

Hi @jbsalis,

You could try DB Browser for SQLite, they support SQLCipher:

https://sqlitebrowser.org

DB Browser was able to open my version 3 SOSdata.db on windows. Nice! But I did not see any command for migrating the db to 4 and saving it. Did I miss it?

Hi @jbsalis,

Yes, it appears that DB Browser is executing other statements which prevent the PRAGMA cipher_migrate command from completing successfully which is unfortunate. A couple of options remain:

  • Use PRAGMA cipher_compatibility set to a value of 3 with the latest SQLCipher for Android library
  • Request a trial of SQLCipher for Windows here which would provide you with the Windows command line shell for 14 days.

This discussion can be closed. I believe my problems are in other parts of my code. Thanks for your help.

Hi @jbsalis,

Thanks for the update. Please feel free to post again if you have questions regarding SQLCipher.