我在下面的链接中遇到与用户相同的问题。他提到,仅在特定的android设备上创建一个空数据库(对我来说,这是像素,对他来说,是另一台android手机)。但是,在大多数android手机上,当前代码中的行为均有效。
有一个解决方案发布,有人提到要在db.close()
之后添加this.getReadableDatabase()
来解决此问题。但是,我不确定为什么要修复它,以及为什么该行为仅在某些Android设备上有效?
答案 0 :(得分:1)
简而言之,如果您使用的是历史上经常使用的方法,则无需使用正确的技术,但如下所示,则必须这样做:-
使用this.getReadableDatabase()
的原因是在data / data / the_package /目录中创建数据库文件夹/目录。如果数据库目录不存在,则资产的典型副本将失败,并出现ENOENT错误。
在默认情况下使用SQLite使用日志模式日志记录的情况下,这没有问题,因此从历史上讲,使用this.getReadableDatabase()
的解决方法一直有效。
但是,在Android Pie(28)中,SDK已更改为默认情况下使用预写日志记录(WAL),这是一种更新的高级日志记录方法。此方法使用两个文件,这些文件具有改进的安全措施。一种是文件被标记/标记为属于创建它们的数据库。
因此,当使用旧方法复制数据库而不关闭数据库时,两个文件(后缀为-wal和-shm的数据库文件)存在,并且很可能包含日志记录数据(例如创建任何表)。但是,它们不会被标记为用于复制数据库,因此(我相信)是重新创建数据库的(因为由于数据库与-shm和-wal文件之间的不匹配而无法打开复制的数据库),因此随之而来的是找不到表错误。
使用WAL关闭数据库/连接会导致提交数据,因此为什么在this.getReadableDatabase()
工作后立即关闭数据库。
但是,正确的解决方法是使用File方法检查并创建数据库目录(如果不存在)。这样就无需打开数据库,这很浪费资源,也不需要关闭数据库,这也浪费了资源(即,实际上已执行已记录的操作,并且将数据写入磁盘以及-wal和-shm文件也会被读取和重写)。
答案 1 :(得分:0)
我认为这个问题是由于每个Android版本都带来了不同的SQLite版本,并且一些供应商也自定义了SQLite库版本。正如您从this link中所读到的:
Android API SQLite Version
API 27 3.19
API 26 3.18
API 24 3.9
API 21 3.8
API 11 3.7
API 8 3.6
API 3 3.5
API 1 3.4
希望有帮助。