安卓SQLite unable to open database file (code 14)异常

用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.sqlite.SQLiteConnection.executeForCursorWindow(SQLiteConnection.java:843)
 at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:836)
at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62)
android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:145)
android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:134)

先回顾下异常场景,常驻线程每10秒定时查询30个记录表的元数据数量,开始一切正常,到了第4分钟,程序在小米4(安卓6.0),在三星手机(安卓5.0)和联想手机(安卓4.3)上异常退出。

第一是猜想是不是数据库文件被清掉,进adb查看下,文件还在数据也没有问题。
这时度娘了下,找到了这边博文
再次非常感谢@梦里风林 博主的分享

https://ahangchen.gitbooks.io/windy-afternoon/content/android/sqlite/SQLITE在ANDROID上的一个BUG.html

结论

这是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/data/com.cmp.pkg/databases/main").mkdir();
            Log.d("ahang", rs + "");
            super.getReadableDatabase().execSQL("PRAGMA temp_store_directory = '/data/data/com.cmp.pkg/databases/main'");
            mainTmpDirSet = true;
            return super.getReadableDatabase();
        } 
        return super.getReadableDatabase();
    }

此时再进行测试,到了第12分钟,程序在小米4(安卓6.0)复现,在三星手机(安卓5.0)和联想手机(安卓4.3)一切正常。

此时,基本上可以定位到这个异常原因了,果然是频繁执行cout(id)操作导致的,此时我采用了在插入记录到数据库时机,和删除记录到数据库时机时用Map维护了一个cout记录,实际上就减少了对数据库的访问,
最后验证成功

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值