最近我得到了很多有关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,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系列中获得这种类型的报告.我不知道什么改变了,因为这个代码一直在工作没有任何问题.有没有我失踪的东西?
解决方法
简短的答案:尝试删除sqliteDatabase.OPEN_READONLY.
更长的答案:
“WAL”是预写日志,这是sqlite中相对较新的功能,据了解. WAL上的sqlite文档说“不可能打开只读WAL数据库”.现在,这似乎在只读媒体的上下文中更多,但它可能适用于OPEN_READONLY.
如果这有帮助,我会有点惊讶,因为它假定:
>标准Android中没有使用WAL
> HTC在这两台设备上启用了WAL
>关于你的环境的一些特别的事情(例如,你的资产的二进制数据库)正在导致这个问题,普通的只读数据库仍然可以正常工作,因为我无法想象这些设备将通过破坏的读取的兼容性测试 – 仅数据库支持
但是,我认为这至少值得一拍.
您还可以考虑从二进制数据库打包到打包sql语句来构建/填充数据库并执行它们.虽然这会更慢(如果不使用事务,速度会慢得多),那么数据库特定于文件的问题可能不那么容易.