1

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.

1
  • Hey, same problem here, did you manage to resolve it? Commented Jan 5 at 12:10

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.