UndeliverableException: android.database.sqlite.SQLiteReadOnlyDatabaseException: попытка записи базы данных только для чтения

Я использую DBFlow с SQLCipher. Я пытаюсь зашифровать уже существующую базу данных SQLite (используя DBFlow) с помощью SQLCipher в Android.

Я использовал следующий код для шифрования БД:

private void encryptDB() {
        SQLiteDatabase.loadLibs(this);
        String password = "test123";
        String LEGACY_DATABASE_NAME = "legacy.db";
        String NEW_DATABASE_NAME = "new_crypt.db";
        File newDBFile = getDatabasePath(NEW_DATABASE_NAME);
        File legacyFile = getDatabasePath(LEGACY_DATABASE_NAME);
        if (!newDBFile.exists() && legacyFile.exists()) {
            SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(legacyFile, "", null);
            db.rawExecSQL(String.format("ATTACH DATABASE '%s' AS encrypted KEY '%s';", newDBFile.getAbsolutePath(), password));
            db.rawExecSQL("SELECT sqlcipher_export('encrypted')");
            db.rawExecSQL("DETACH DATABASE encrypted;");
            db.close();
            db = SQLiteDatabase.openDatabase(newDBFile.getAbsolutePath(), password, null, SQLiteDatabase.OPEN_READWRITE);
            db.close();
            legacyFile.delete();
            newDBFile.renameTo(legacyFile);
        }
    }

БД зашифрована нормально, но когда я пытаюсь написать какие-либо операции:

Place place = new Place();
place.setName("Test");
place.save();

Модель БД:

@Table(database = DatabaseManager.class)
public class Place extends BaseModel {
  @Column
  String name;
  // set and get methods goes here
}

затем получить следующее исключение:

io.reactivex.exceptions.UndeliverableException: android.database.sqlite.SQLiteReadOnlyDatabaseException: попытка записи базы данных только для чтения (код 1032 SQLITE_READONLY_DBMOVED[1032])

Я нашел аналогичный пост здесь, но не нашел для него решения.

Кроме того, я нашел это для шифрования базы данных DBFlow с помощью SQLCipher и реализовал его. Затем оно работает, если я устанавливаю его как новое приложение, но когда я устанавливаю это приложение поверх старого приложения, в котором не зашифрована БД, оно терпит неудачу.

net.sqlcipher.database.SQLiteException: файл не является базой данных: при компиляции: выберите count(*) из sqlite_master;

Пожалуйста, предложите, как я могу это исправить?


person Shailendra Madda    schedule 23.04.2021    source источник
comment
когда я пытаюсь написать какие-либо операции - ваш вопрос не показывает никаких операций записи, кроме самого исходного шифрования. Я не использовал DBFlow, но, учитывая сообщение об ошибке, кажется, что вы оставили какой-то объект DBFlow, который запоминает предварительно зашифрованную базу данных. Также обратите внимание, что вы теряете соединение с базой данных в encryptDB(), поскольку вы вызываете openDatabase(), не закрывая его. Кроме того, у вас есть открытое соединение с базой данных из этого вызова openDatabase(), когда вы переименовываете файл. Перед шифрованием закройте все подключения к базе данных.   -  person CommonsWare    schedule 23.04.2021
comment
Операции записи выполняются после шифрования БД. Даже я пытался закрыть БД, как db.close(), но та же ошибка.   -  person Shailendra Madda    schedule 23.04.2021
comment
@CommonsWare Я обновил свой вопрос, как я выполняю операцию записи в таблице Place с помощью DB Flow. Не подскажете, что здесь делать?   -  person Shailendra Madda    schedule 06.05.2021