Android P(8.1)模拟器SQLite表缺失问题求助
Android P 模拟器数据库拷贝后表缺失的解决方案
这个问题我之前帮不少开发者排查过,确实是Android P(API 28)引入的SQLite行为变更导致的,核心原因和WAL(Write-Ahead Logging)模式有关,下面给你拆解原因和解决方案:
为什么只有Android P会出问题?
在Android 8.1(Oreo MR1,API 27)及以下版本,SQLite默认使用DELETE日志模式,这种模式下数据库只依赖单个.db文件,所以你直接拷贝assets里的数据库文件就能正常加载表。
但从Android P(API 28)开始,系统默认启用了WAL模式——这是一种性能更优的数据库写入模式,但它会依赖额外的两个辅助文件:你的数据库名.db-wal和你的数据库名.db-shm。如果你的拷贝逻辑只处理了主.db文件,没有处理这两个辅助文件(或者目标目录里残留了旧的辅助文件),SQLite就会无法正确加载原数据库的表结构,甚至会自动重建一个空数据库,自然就会抛出no such table的错误。
解决方案(任选其一即可)
方案1:预先生成数据库时禁用WAL模式
这是最省心的方案,从根源避免依赖辅助文件:
- 用SQLite管理工具(比如SQLiteStudio、Navicat)打开你要放到assets里的原始数据库
- 执行SQL命令:
PRAGMA journal_mode=DELETE; - 保存数据库并替换assets里的旧文件
- 保持你原来的拷贝逻辑不变即可,因为此时数据库回到了传统的单文件模式
方案2:修改拷贝代码,处理WAL相关文件
如果你需要保留WAL模式的性能优势,可以修改你的拷贝逻辑,确保清理残留的辅助文件:
public void createDataBase() throws IOException { String dbName = "你的数据库名.db"; File dbFile = getDatabasePath(dbName); boolean dbExist = dbFile.exists(); if (dbExist) { // 先删除残留的WAL和SHM文件,避免和新拷贝的数据库冲突 File walFile = new File(dbFile.getAbsolutePath() + "-wal"); File shmFile = new File(dbFile.getAbsolutePath() + "-shm"); if (walFile.exists()) walFile.delete(); if (shmFile.exists()) shmFile.delete(); } else { // 创建空数据库占位,然后拷贝assets中的文件 this.getReadableDatabase().close(); copyDataBase(dbName); } } private void copyDataBase(String dbName) throws IOException { InputStream myInput = getAssets().open(dbName); String outFileName = getDatabasePath(dbName).getAbsolutePath(); OutputStream myOutput = new FileOutputStream(outFileName); byte[] buffer = new byte[1024]; int length; while ((length = myInput.read(buffer)) > 0) { myOutput.write(buffer, 0, length); } myOutput.flush(); myOutput.close(); myInput.close(); }
方案3:拷贝后强制切换到DELETE模式
如果不想修改原始数据库,也可以在拷贝完成后,打开数据库并执行切换命令:
// 拷贝完成后调用这个方法 private void disableWAL() { SQLiteDatabase db = SQLiteDatabase.openDatabase( getDatabasePath("你的数据库名.db").getAbsolutePath(), null, SQLiteDatabase.OPEN_READWRITE ); db.execSQL("PRAGMA journal_mode=DELETE;"); db.close(); }
额外提醒
如果你之前在Android P模拟器上运行过旧版本的代码,建议先卸载应用或者清除应用数据,确保目标目录里没有残留的旧辅助文件,再测试修改后的代码。
内容的提问来源于stack exchange,提问作者Gaurav Jain
相关产品推荐
相关产品推荐

