安卓SQLiteunabletoopendatabasefile(code14)异常
⽤SQLite做记录数据库⽤时,出现了如下异常
E/CrashRecorder: android.database.sqlite.SQLiteCantOpenDatabaseException:
unable to open database file (code 14)
at android.database.sqlite.SQLiteConnection.nativeExecuteForCursorWindow(Native Method)
at android.database.uteForCursorWindow(SQLiteConnection.java:843)
at android.database.uteForCursorWindow(SQLiteSession.java:836)
at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62)
android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:145)
unableandroid.database.Count(SQLiteCursor.java:134)
先回顾下异常场景,常驻线程每10秒定时查询30个记录表的元数据数量,开始⼀切正常,到了第4分钟,程序在⼩⽶4(安卓6.0),在三星⼿机(安卓5.0)和联想⼿机(安卓4.3)上异常退出。
第⼀是猜想是不是数据库⽂件被清掉,进adb查看下,⽂件还在数据也没有问题。
这时度娘了下,到了这边博⽂
再次⾮常感谢@梦⾥风林 博主的分享
结论
这是sqlite在Android系统上的⼀个bug,在需要建⽴索引的sql语句频繁执⾏时,会发⽣这个异常。
(如果你是在SQLiteDatabase执⾏open()时看到的这个exception,那应该是线程冲突的问题,跟这篇⽂章讲的不是同⼀个) 根本原因是sqlite临时⽂件⽬录不可⽤。 解决⽅案是第⼀次建⽴连接时设置临时⽂件⽬录。
在项⽬⾥遇到了这样⼀个奇怪的crash,长期占据各个版本crash上报榜⾸,但在开发中⼀直不能重现。
在许多查DB的代码路径⾥,都会在moveToFirst(),getCount()等需要执⾏fillWindow的地⽅出现这个crash。
按照他的思路,先把这些操作全部try – catch住
然后修改代码
PRAGMA temp_store_directory = 'your dir'
//这个东西仅对当前SqliteConncetion有效,
//在第⼀次建⽴sqlite连接的时候(我是重写了getReadabelDatabase()⽅法),设置⼀下临时⽂件⽬录,like this:
//private static boolean mainTmpDirSet = false;
@Override
public SQLiteDatabase getReadableDatabase() {
if (!mainTmpDirSet) {
boolean rs = new File("/data/p.pkg/databases/main").mkdir();
Log.d("ahang", rs + "");
mainTmpDirSet = true;
ReadableDatabase();
}
ReadableDatabase();
}
此时再进⾏测试,到了第12分钟,程序在⼩⽶4(安卓6.0)复现,在三星⼿机(安卓5.0)和联想⼿机(安卓4.3)⼀切正常。
此时,基本上可以定位到这个异常原因了,果然是频繁执⾏cout(id)操作导致的,此时我采⽤了在插⼊记录到数据库时机,和删除记录到数据库时机时⽤Map维护了⼀个cout记录,实际上就减少了对数据库的访问,
最后验证成功

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。