HTC Desire HD的Sqlite问题

Gre*_*lli 9 sqlite android

最近我收到很多关于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
Run Code Online (Sandbox Code Playgroud)

然后我的应用程序基本上在火焰中燃烧,因为打开数据库的调用导致严重的运行时错误,当光标保持打开时,它会显示出来.此时不应该有光标,因为我们正试图打开它.

这只发生在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);
}
Run Code Online (Sandbox Code Playgroud)

可悲的是,这款手机仅在英国上市,我的库存中没有.我只从HTC Desire系列中获得此类报告.我不知道是什么改变了,因为这段代码一直没有任何问题.有什么我想念的吗?

Com*_*are 20

简短的回答:尝试删除SQLiteDatabase.OPEN_READONLY.

更长的回答:

"WAL"是预写日志,在我理解的SQLite中是一个相对较新的特性.WAL上的SQLite文档说"打开只读的WAL数据库是不可能的".现在,这似乎更多是在只读媒体的背景下,但它可能适用于OPEN_READONLY.

如果这有帮助,我会感到有些惊讶,因为它假定:

  • WAL不用于标准Android
  • HTC在这两个设备上启用了WAL
  • 关于你的环境的一些特别之处(例如,你正在从资产中取出的二进制数据库)导致这个问题,普通的只读数据库仍能正常工作,因为我无法想象那些设备会通过兼容性测试而破坏读取只有数据库支持

但是,我认为这至少值得一试.

您还可以考虑从打包二进制数据库切换到打包SQL语句以构建/填充数据库并执行它们.虽然这会更慢(如果不使用事务,速度会慢得多),但它可能不太容易出现数据库文件特定的问题.

  • @CommonsWare确实Android最近没有使用WAL和HTC启用它.关于这方面的更多讨论在这里:http://forum.xda-developers.com/showthread.php?t = 889999 (2认同)