使用 SQLCipher加密数据库的错误总结(file is not a database: , while compiling: select count(*) from sqlite_master

使用经历如下

  由于项目中需要用到加密数据库,使用特意用了github的经典项目 sqlcipher, 使用起来也很简单,和原生的数据库没有差异,甚至连类名都一样,只是包路径需要替换为Sqlcipher的相应路径。还有获取数据库的方式需要加上密码,如 SQLiteOpenHelper.getWritableDatabase(“secret”)。一开始接入也没有想太多,就直接用了。没想到,后来bugly发现了一些bug的描述,是关于这个加密数据库,大致错误描述如下:file is not a database: , while compiling: select count(*) from sqlite_master。当然首先会去百度进行搜索,也去github项目的issue,得到的答案就是说加解密数据库使用的密码不一样,导致解密失败,不是数据库的格式,所以抛异常。
使用 SQLCipher加密数据库的错误总结(file is not a database: , while compiling: select count(*) from sqlite_master_第1张图片

解决问题的过程

  1. 一开始抱着这种思路去解决问题,因为本身自己在使用加密数据库的时候,密码是字符串加上Build.BOARD组成,所以猜测是Build.BOARD变化了,导致密码不同而导致。碰巧的是,刚刚好有一个用户遇上这个问题,所以立马打了一个包给他,满心以为会正常,因为这一次密码是固定的字符串,没想到还是报错。他的手机是坚果R1。
  2. 在bugly上面,这个bug不关乎机型,是偶现导致的,猜测是SqlCipher库可能在某些异常情况不够完善导致的,所以决定换个思路,寻找新的替换库。皇天不负有心人,找到了腾讯开源的数据库WCDB。WCDB的特性如下:
    使用 SQLCipher加密数据库的错误总结(file is not a database: , while compiling: select count(*) from sqlite_master_第2张图片
    发现WCBD加密也是基于SQLCipher,难道微信在使用的时候就不会发生那个闪退吗,抱着这个想法,我查看了WCDB的wiki介绍。wiki
    使用 SQLCipher加密数据库的错误总结(file is not a database: , while compiling: select count(*) from sqlite_master_第3张图片
    简直是完美,WCDB支持SQLCipher无缝迁移, 只需要指定之前的数据库名字和使用的SQLCipher版本既可。查看了WCDB的源码可知,WCDB内置了一个数据库损害处理器DatabaseErrorHandler,在数据库发生异常的时候,可以进行自定义的修复,当然WCDB默认提供的是重新创建数据库。

  3. 很快换上了WCDB,替换成本也很低,基本就是替换包路径。重新打包发给用户安装,这一次成功了,没有发生崩溃!!!。写这个博客的时候,已经上线半个月了,bugly也没有相关的错误了,所以就是成功修复了这个bug。

  4. 由于对源码的阅读还不够,个人猜测是初始化数据库的时机或者机制导致的,可能WCDB在初始化数据库的时候做了重新尝试。

总结

  这一次使用开源库的教训就是要事先调研这个库,查看issue还有相关博客的介绍,看看这个库是不是有坑没填,或者是说有其他替换的更完善的库,例如微信的WCDB。还有就是解决问题也不能一根筋,如果用到的第三方库实在有缺陷,只能考虑使用其他第三方库进行兼容处理。

你可能感兴趣的:(解决问题,Android数据库)