gpt4 book ai didi

android - Assets 文件夹中的 SQLite 数据库在 Android Pie 中不起作用,即 API 28

转载 作者:搜寻专家 更新时间:2023-10-30 22:25:13 27 4
gpt4 key购买 nike

我已经在我的 Assets 文件夹中添加了 sqlite 文件,并在我的应用程序中使用了 sqlite 文件中的数据。它在 API 27(即牛轧糖)之前运行良好。但是该应用程序因 Android Pie 即 API 28 而崩溃。我通过以下方式在我的数据库帮助程序类中使用以下方法。请帮帮我。

    public Database(Context context, String databaseName) {
super(context, databaseName, null, DATABASE_VERSION);
this.context = context;
String packageName = context.getPackageName();
DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
DB_NAME = databaseName;
openDataBase();
}

public void createDataBase() {
boolean dbExist = checkDataBase();
if (!dbExist) {
this.getReadableDatabase();
try {
copyDataBase();
} catch (IOException e) {
Log.e(this.getClass().toString(), "Copying error");
throw new Error("Error copying database!");
}
}else{
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
int dbVersion = prefs.getInt(SP_KEY_DB_VER, 1);
if (DATABASE_VERSION != dbVersion) {
File dbFile = context.getDatabasePath(DB_NAME);
if (dbFile.delete()) {
database.deleteDatabase(new File(DB_PATH + DB_NAME));
openDataBase();
}
}
}
}

private boolean checkDataBase() {
SQLiteDatabase checkDb = null;
try {
String path = DB_PATH + DB_NAME;
//checkDb = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY);
checkDb = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY);
} catch (SQLException e) {
Log.d(TAG, "Error while checking db");
}
if (checkDb != null) {
checkDb.close();
}
return checkDb != null;
}

private void copyDataBase() throws IOException {
InputStream externalDbStream = context.getAssets().open(DB_NAME);

String outFileName = DB_PATH + DB_NAME;

OutputStream localDbStream = new FileOutputStream(outFileName);

byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = externalDbStream.read(buffer)) > 0) {
localDbStream.write(buffer, 0, bytesRead);
}
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = prefs.edit();
editor.putInt(SP_KEY_DB_VER, DATABASE_VERSION);
editor.commit();
localDbStream.close();
externalDbStream.close();
}


public SQLiteDatabase openDataBase() throws SQLException {

String path = DB_PATH + DB_NAME;
if (database == null) {
createDataBase();
database = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READWRITE);
}
return database;
}

这些是我正在使用的 openDatabase、copyDatabase 和创建数据库方法。

这是崩溃日志 -

android.database.sqlite.SQLiteException: no such table: quran_chapters (code 1 SQLITE_ERROR): , while compiling: SELECT * FROM quran_chapters at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method) at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:903) at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:514) at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588) at android.database.sqlite.SQLiteProgram.(SQLiteProgram.java:58) at android.database.sqlite.SQLiteQuery.(SQLiteQuery.java:37) at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:46) at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1408) at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1347)

最佳答案

如果数据库不存在,您将使用 this.getReadableDatabase(); 创建数据库,因为您可能在 onCreate 方法中未执行任何操作,数据库为空。

然后您用副本覆盖磁盘,但是由于数据库仍处于打开状态(通过 this.getReadableDatabase();),空的、无表的数据库可能会完全保留在缓存中,因此会出现问题。

使用一种在数据库不存在时打开数据库的方法似乎是试图解决当它是第一个数据库时复制失败并且在那个阶段应用程序的存储没有名为 databases 的目录(打开它会创建目录)。

  • 请注意,在大多数情况下,getReadableDatabase 将获得一个可写数据库。

我个人更喜欢,并且没有遇到任何问题:-

  1. 从不对数据库路径进行硬编码,而是始终使用 Context 的 getDatabasePath 方法。例如:- mDBPath = context.getDatabasePath(database).getPath();
  2. 检查数据库文件是否存在是为了查看数据库是否存在,而不是打开数据库查看是否存在。 (见示例3)

  3. 检查数据库的父级(即数据库文件夹)以查看它是否存在,如果不存在,则使用文件的 mkdirs 方法创建数据库目录。例如:-

    private boolean ifDatabaseExists(String dbpath) {
    文件数据库=新文件(数据库路径);
    如果(db.exists())返回真;
    文件目录 = 新文件 (db.getParent());
    如果(!dir.exists()){
    目录.mkdirs();
    }
    返回假;
    }

  4. 将数据库从assets复制到1处获取的路径指定的位置。

    • 作为 4 的一部分,我获取 Assets 文件,检查前 16 个字节以查看它是否是有效的 SQLiteDatabase(必须是“SQLite format 3\u0000”)。

    • 然后继续将数据库从 Assets 复制到数据库文件。

关于android - Assets 文件夹中的 SQLite 数据库在 Android Pie 中不起作用,即 API 28,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53517920/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com