iOS获取通话记录
前言
iOS8.3
之后,存放通话日志的数据库的位置换成了/private/var/mobile/Library/CallHistoryDB/
目录,数据库名为CallHistory.storedata
,由于其采用了Sqlite
的wal
机制,所以还有两个文件,分别为CallHistory.storedata-shm
、CallHistory.storedata-wal
,一开始想得很简单,直接使用Sqlite
打开该数据库,读取即可,后来发现使用NSFileManager
并不能获取到该文件。接下来将详细列出解决思路。
读取通话日志文件
直接使用NSFileManager
不能获取到通话日志文件的原因很简单,因为App本身是在一个沙盒里面的,App只能访问自己的存储空间,系统有一套安全机制来对其进行限制。所以,首先得解决这个限制,解决方案是添加Entitlements授权,在Entitlements文件中添加如下代码:
1 | <key>com.apple.security.exception.files.absolute-path.read-write</key> |
这样,就能访问到通话日志文件。
使用Sqlite
读取数据库
使用Sqlite
直接读取数据库内容时,发现,在调用int errorCode = sqlite3_prepare_v2(database,[sqlStatement UTF8String],-1,&compiledStatement, NULL);
时,出现错误,错误代码为SQLITE_AUTH
,既没有权限,最后解决方案是,将3个文件内容读出,并保存到App自己的存储空间中,比如Cache
目录中,再对保存到App存储目录中的数据库文件进行操作即可。
解决wal
模式问题
由于通话日志的数据库采用了新的事务设计wal
(write-ahead logging),数据库修改后,首先会把修改内容写入日志(-wal),为了提高性能创建了一个内存索引(-shm),映射每一个page是否dirty,读取时先看需要的page是否在wal
日志中,然后再读取,当达到一定条件后Sqlite会自动将数据flush到数据库文件,当然也可以手动flush,在打开数据库之后,调用sqlite3_wal_checkpoint(database, NULL);
即可手动flush
结束
解决这几个问题后,就能成功读取通话日志了,其他的日志,如短信等等同理都可以读取到。