Есть ли проблема в практике, которую я применяю (используя существующую базу данных, расположенную в папке ресурсов)?
Не совсем так, как эторекомендуемая и часто используемая техника.Однако при неправильной реализации могут возникнуть проблемы, особенно сейчас.
В соответствии с быстрым поиском операционная система устройства Android 8.0 (Oreo), с возможностью обновления до Android 9.0 (Pie) ;ZenUI 5
Конечно, при использовании Android Pie выявляется 1 проблема, с которой вы могли столкнуться.
Причиной является использование this.getReadableDatabase();
до вызова метода copyDatabase .
Поскольку Android Pie включает WAL (запись с опережением записи), по умолчанию создаются два файла: -wal и -shm .Эти оставшиеся вызывают конфликт, поскольку они не соответствуют базе данных, которая была только что скопирована.Я считаю, что конечным результатом является то, что скопированная база данных удаляется и создается совершенно новая, чтобы обеспечить пригодную для использования базу данных.Как таковых таблиц и базовых данных не существует.Это часто приводит к тому, что в таблице не найдена ошибка / исключение, как правило, когда делается попытка получить доступ к данным, которых таблица не существует.
Что я могу сделать, чтобы избежать этого исключения?
Исправление 1
Простое исправление, но не рекомендуемое исправление, заключается в переопределении SQLiteOpenhelper onConfigure .в WordDbHelper.java для вызова метода disableWriteAheadLogging .
Однако применение этого исправления означает, что вы упускаете преимущества Запись в журнал с записью впереди .
Исправление 2
Правильное исправление - не использовать getReadableDatabase перед копированием.Похоже, это было историческим решением простой проблемы.Это каталог data / data / the_package / для пакета, для новой установки приложения, который не имеет каталога database .Таким образом, getWritableDatabase (или getReabableDatabase, которая получает доступную для записи базу данных, если она может) создает каталог, а также базу данных, которая затем перезаписывается.
Что приложение должно сделать, это проверить, существует ли каталог, и затем создать его,все это можно сделать в методе checkDataBase, используя что-то вроде: -
private boolean checkDataBase() {
File db = new File(DATABASE_PATH + DATABASE_NAME);
if(db.exists()) return true;
File dir = new File(db.getParent());
if (!dir.exists()) {
dir.mkdirs();
}
return false;
}
- , отметьте, что вам следует дополнительно удалить строку
this.getReadableDatabase();
из метода createDatabase .
Хотя, вероятно, это не проблема, гораздо мудрее НЕ когда-либо жестко кодировать путь к базе данных, а вместо этого использовать метод класса Context ' getDatabasePath (если используется стандартное / рекомендуемое расположение длябаза данных).например,
private boolean checkDataBase() {
File db = new File(context.getDatabasePath(DBNAME)); //<<<<<<<<<< CHANGED
if(db.exists()) return true;
File dir = new File(db.getParent());
if (!dir.exists()) {
dir.mkdirs();
}
return false;
}
Примечание
Из предоставленной трассировки стека, а также MainActivity.java , WordProvidr.java и WordDBHelper имеют идентичный код, точную причину определить невозможно.Таким образом, вышеизложенное является вероятной причиной или причиной, которая может произойти.