Anshuman Biswal
Anshuman Biswal

Reputation: 11

Crash while migrating from net.zetetic:android-database-sqlcipher:3.5.9 to 4.5.4

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

Answers (0)

Related Questions