Импорт и экспорт базы данных не работает в Android Pie - PullRequest
0 голосов
/ 05 января 2019

Ниже приведен рабочий метод импорта и экспорта базы данных SQLite. Работает нормально во всех версиях Android, кроме Android Pie. Когда я пытаюсь импортировать в Android пирог, он показывает успешный тост, но база данных не восстанавливается. Кто-нибудь может мне помочь обойти в Android Pie (API 28).

private void importDB() {

    try {
        File sd = Environment.getExternalStorageDirectory();
        File cur_db_pat = new File(this.getDatabasePath(DATABASE_NAME).getAbsolutePath());

        if (sd.canWrite()) {
            String backupDBPath = bac_dir_nam +"/" + DATABASE_NAME;
            File currentDB = new File(sd, backupDBPath);

            FileChannel src = new FileInputStream(currentDB).getChannel();
            FileChannel dst = new FileOutputStream(cur_db_pat).getChannel();
            dst.transferFrom(src, 0, src.size());
            src.close();
            dst.close();
            Toast.makeText(getBaseContext(), cur_db_pat.toString(),
                    Toast.LENGTH_LONG).show();
        }
    } catch (Exception e) {

        Toast.makeText(getBaseContext(), e.toString(), Toast.LENGTH_LONG)
                .show();

    }
}

private void exportDB() {

    try {
        File sd = Environment.getExternalStorageDirectory();
        File cur_db_pat = new File(this.getDatabasePath(DATABASE_NAME).getAbsolutePath());

        if (sd.canWrite()) {
            String backupDBPath = bac_dir_nam+"/" + DATABASE_NAME;
            File backupDB = new File(sd, backupDBPath);

            FileChannel src = new FileInputStream(cur_db_pat).getChannel();
            FileChannel dst = new FileOutputStream(backupDB).getChannel();
            dst.transferFrom(src, 0, src.size());
            src.close();
            dst.close();
            Toast.makeText(getBaseContext(), backupDB.toString(),
                    Toast.LENGTH_LONG).show();

        }
    } catch (Exception e) {

        Toast.makeText(getBaseContext(), e.toString(), Toast.LENGTH_LONG)
                .show();

    }
}

У меня нет большого опыта работы с файловой системой. Так что пример очень поможет.

1 Ответ

0 голосов
/ 06 января 2019

В Android Pie + SQLite по умолчанию заменено на использование в общем более эффективного ведения журнала записи вперед ( WAL ) вместо режима журнала.

Таким образом, будут два файла с тем же именем, что и у базы данных, но с суффиксами -shm (файл с общей памятью) и -wal (журнал записи вперед) и их наличие. это то, что я считаю, вызывает проблему (ы). Временные файлы, используемые SQLite (см. 2.2 и 2.3)

Одним из исправлений было бы отключение записи в журнал впереди с использованием метода SQliteDatabase disableWriteAheadLogging , и предыдущий метод работал бы так же, как и раньше, но с менее эффективным режимом журнала.

  • (при использовании подкласса SQliteOpenHelper затем переопределить метод onConfigure для вызова этого метода.) disableWriteAheadLogging .

Другим исправлением является удаление этих двух файлов при восстановлении. Чтобы избежать возможного повреждения, вы должны убедиться, что база данных была должным образом проверена перед созданием резервной копии. см. контрольная точка PRAGMA;

Ниже приведен фрагмент, который удаляет эти два файла при восстановлении (отмечая, что резервное копирование предположительно было выполнено с соответствующей контрольной точкой): -

                    // Added for Android 9+ to delete shm and wal file if they exist
                    File dbshm = new File(dbfile.getPath() + "-shm");
                    File dbwal = new File(dbfile.getPath()+ "-wal");
                    if (dbshm.exists()) {
                        dbshm.delete();
                    }
                    if (dbwal.exists()) {
                        dbwal.delete();
                    }

Другим исправлением будет дополнительное резервное копирование и последующее восстановление файлов -shm и -wal.

Вы можете также пожелать рассмотреть потенциальные преимущества переименования исходных файлов при импорте / восстановлении, проверки новых файлов после их копирования (например, с использованием PRAGMA целостность_чека; ), если результаты указывают Нет проблем, затем удалите переименованные исходные файлы, в противном случае удалите импортированные файлы и переименуйте исходные файлы в их исходное имя, указывая, что импорт не удался.

...