最近我收到很多关于HTC Desire系列的抱怨,并且在调用sql语句时失败了。我收到了包含以下内容的用户的报告。
I/Database( 2348): sqlite returned: error code = 8, msg = statement aborts at 1: [pragma journal_mode = WAL;]
E/Database( 2348): sqlite3_exec to set journal_mode of /data/data/my.app.package/files/localized_db_en_uk-1.sqlite to WAL failed
其次是我的应用程序基本上在火焰中燃烧,因为打开数据库的调用导致严重的运行时错误,当游标保持打开时显示自身错误。此时不应该有光标,因为我们正试图打开它。
这只发生在HTC Desire HD和Z.我的代码基本上执行以下操作(稍微更改以隔离问题区域)。
SQLiteDatabase db;
String dbName;
public SQLiteDatabase loadDb(Context context) throws IOException{
//Close any old db handle
if (db != null && db.isOpen()) {
db.close();
}
// The name of the database to use from the bundled assets.
String dbAsset = "/asset_dir/"+dbName+".sqlite";
InputStream myInput = context.getAssets().open(dbAsset, Context.MODE_PRIVATE);
// Create a file in the app's file directory since sqlite requires a path
// Not ideal but we will copy the file out of our bundled assets and open it
// it in another location.
FileOutputStream myOutput = context.openFileOutput(dbName, Context.MODE_PRIVATE);
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
// Close the streams
myOutput.flush();
// Guarantee Write!
myOutput.getFD().sync();
myOutput.close();
myInput.close();
// Not grab the newly written file
File fileObj = context.getFileStreamPath(dbName);
// and open the database
return db = SQLiteDatabase.openDatabase(fileObj.getAbsolutePath(), null, SQLiteDatabase.OPEN_READONLY | SQLiteDatabase.NO_LOCALIZED_COLLATORS);
}
可悲的是,这款手机仅在英国上市,我的库存中没有。我只从HTC Desire系列中获得此类报告。我不知道是什么改变了,因为这段代码一直没有任何问题。有什么我想念的吗?
答案 0 :(得分:20)
简短回答:尝试删除SQLiteDatabase.OPEN_READONLY
。
更长的答案:
“WAL”是预写日志,在我理解的SQLite中是一个相对较新的功能。 WAL上的SQLite文档说“打开只读的WAL数据库是不可能的”。现在,这似乎更多地出现在只读媒体的背景下,但它可能适用于OPEN_READONLY
。
如果这有所帮助,我会感到有些惊讶,因为它假定:
但是,我认为这至少值得一试。
您也可以考虑从打包二进制数据库切换到打包SQL语句以构建/填充数据库并执行它们。虽然这会更慢(如果不使用事务,速度会慢得多),但它可能不太容易出现数据库文件特定的问题。
答案 1 :(得分:0)
这里的基本问题是你假设sqlite3数据库文件在Android设备中是可移植的。这不是真的。文件格式 - 实际上,完全使用SQLite作为数据库引擎 - 是不是 API的一部分。 HTC可以生产一款使用postgres而不是sqlite3的Android手机,它仍然可以正式兼容。
是的,通过在应用程序的资产中捆绑sqlite3 .db文件,然后在安装后完整地使用它来预填充数据库内容是一种常见的技巧。但是,即使在运行相同版本的Android平台的设备之间也不能保证工作。您唯一可以确定的是,在运行给定Android版本的给定设备上创建的.db文件将继续在同一物理设备上运行,运行相同或更高版本的Android版本来自同一系统供应商。
(甚至不是来自同一供应商的相同型号的设备?否:不能保证以相同方式标记的两个设备实际上在引擎盖下运行相同的系统构建,或者确实在不同时间点必须具有相同的硬件在他们的产品生命周期中。)
可移植的唯一方法是不嵌入原始数据库文件本身,而是嵌入可以在公共API中播放的通用可解析表示,以建立适合设备的数据库文件。