Reputation: 11
I am migrating from net.zetetic:android-database-sqlcipher:3.5.9 to 4.5.4 on my Android project. Here is the given code before update:-
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String DBNAME = "demo_app";
private static final int VERSION = 12;
private SQLiteDatabase database;
private Context context;
private static DatabaseHelper _instance;
private static final String CREATE_PERFORMANCE = "create table performance ( id text primary key,.....";
public static final String[] PERFORMANCE_COLUMNS = new String[] { "id", "event_name", "start_utc", ....;
private static final String CREATE_TICKET = "create table ticket ( id text primary key, ...";
public static final String[] TICKET_COLUMNS = new String[] { "id", "name", "buyer_id", "section_name", ....;
public static DatabaseHelper getInstance(Context context) {
if (_instance == null) {
_instance = new DatabaseHelper(context);
}
return _instance;
}
private DatabaseHelper(Context context) {
super(context, DBNAME, null, VERSION);
this.context = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_PERFORMANCE);
db.execSQL(CREATE_TICKET);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS ticket"); //
db.execSQL("DROP TABLE IF EXISTS performance"); //
onCreate(db);
}
public DatabaseHelper open() throws SQLException {
SQLiteDatabase.loadLibs(this.context);
database = this.getWritableDatabase(Constants.api_secret);
return this;
}
public SQLiteDatabase getDatabase() {
if (database == null) {
SQLiteDatabase.loadLibs(this.context);
database = getWritableDatabase(Constants.api_secret);
}
return database;
}
public void clearTables() {
getDatabase().execSQL("delete from ticket");
getDatabase().execSQL("delete from performance");
}
}
after updating to 4.5.4 here are my changes. Everything else remains the same.
private DatabaseHelper(Context context) {
super(context, DBNAME, null, VERSION, new SQLiteDatabaseHook() {
@Override
public void preKey(SQLiteDatabase sqLiteDatabase) {
// No-op
}
@Override
public void postKey(SQLiteDatabase sqLiteDatabase) {
Executors.newSingleThreadExecutor().execute(new Runnable() {
@Override
public void run() {
try (Cursor cursor = sqLiteDatabase.rawQuery("PRAGMA cipher_migrate", null)) {
if (cursor != null && cursor.moveToFirst()) {
int result = cursor.getInt(0);
if (result == 0) {
Log.d("DataBaseHelper", "Migration is successful");
} else {
throw new SQLiteException("Cipher migration failed");
}
} else {
throw new SQLiteException("No result from PRAGMA cipher_migrate");
}
} catch (Exception e) {
throw new SQLiteException("Error executing PRAGMA cipher_migrate", e);
}
}
});
}
});
this.context = context;
}
I made changes after going through the documentation. https://discuss.zetetic.net/t/upgrading-to-sqlcipher-4/3283/6 https://discuss.zetetic.net/t/error-migrating-from-version-3x-to-4x/6360/5
But I am seeing below crashes
there are 2 FATAL EXCEPTIONS One during migration and another during clearTable
First crash point:- Inside asyncTask first we are calling clearTables
public void clearTables() {
getDatabase().execSQL("delete from ticket");
getDatabase().execSQL("delete from performance");
}
public SQLiteDatabase getDatabase() {
if (database == null) {
QLiteDatabase.loadLibs(this.context);
database = getWritableDatabase(Constants.api_secret); // this is the last call from app’s class DatabaseHelper before crash.
}
return database;
}
2024-06-26 08:06:54.353 13645-13769 AndroidRuntime com.ticke.android.app E FATAL EXCEPTION: AsyncTask #1
Process: com.ticke.android.app, PID: 13645
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$4.done(AsyncTask.java:415)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:381)
at java.util.concurrent.FutureTask.setException(FutureTask.java:250)
at java.util.concurrent.FutureTask.run(FutureTask.java:269)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
at java.lang.Thread.run(Thread.java:1012)
Caused by: android.database.sqlite.SQLiteException: unable to close due to unfinalized statements or unfinished backups: sqlite3_close() failed
at net.sqlcipher.database.SQLiteDatabase.dbclose(Native Method)
at net.sqlcipher.database.SQLiteDatabase.openDatabaseInternal(SQLiteDatabase.java:2635)
at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1250)
at net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1325)
at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:167)
at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:136)
at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:132)
at com.demo.android.app.common.services.DatabaseHelper.getDatabase(DatabaseHelper.java:124)
at com.demo.android.app.common.services.DatabaseHelper.clearTables(DatabaseHelper.java:130)
atcom.demo.android.app.common.services.DatabaseHelper$StoreUserTicketListTask.doInBackground(Databa seHelper.java:146) atcom.demo.android.app.common.services.DatabaseHelper$StoreUserTicketListTask.doInBackground(Databa seHelper.java:140)
at android.os.AsyncTask$3.call(AsyncTask.java:394)
at java.util.concurrent.FutureTask.run(FutureTask.java:264)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
at java.lang.Thread.run(Thread.java:1012)
=============================================================== Below exception is occuring because at postKey() , after executing PRAGMA cipher_migrate ,the cursor is null ,so we are thowing exception.
2024-06-26 08:06:54.356 13645-13770 AndroidRuntime com.demo.android.app E FATAL EXCEPTION: pool-11-thread-1
Process: com.demo.android.app, PID: 13645
android.database.sqlite.SQLiteException: Error executing PRAGMA cipher_migrate
at com.demo.android.common.services.DatabaseHelper$1$1.run(DatabaseHelper.java:91)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
at java.lang.Thread.run(Thread.java:1012)
Caused by: android.database.sqlite.SQLiteException: Cipher migration failed
at com.demo.android.common.services.DatabaseHelper$1$1.run(DatabaseHelper.java:84)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
at java.lang.Thread.run(Thread.java:1012)
I tried migrating the lib as per documentation. I have executed PRAGMA cipher_migrate at postKey() but,cursor is null , leading to crashes while closing db.Kindly help on this.Stuck since long time.
Upvotes: 1
Views: 113