关于android存储的有三种方式: SharePrference、文件系统和 数据库,这些信息里都用到了,数据库provider存储短信和彩信的基本信息,SharePrference存储关于信息设置的数据,而彩信中每一个媒体文件则是通过文件保存的。
信息的数据库位置 : data/data/com.android.provider.telephonymmssms.db,
同样在这个目录下,如果有彩信则会生成一个app_parts的文件夹,里面保存着彩信中媒体文件,
在data/data/com.android.mms这个目录以Shareprference形式保存着关于信息设置的数据(比如每个会话存多少信息,是否请求递送报告)。
本文重点关注数据库mmssms.db,其中包括 addr、android_metadata、attachments、canonical_addresses、drm、part、pdu、pending_msgs、rate、raw、sms、sr_pending、 threads、words、words_content、words_segdir、words_segments、sqlite_master和sqlite_temp_master一共19张表。
android_metadata 存储的是语言信息,sqlite_master和sqlite_temp_master是系统表,这三张表我们不关心。
addr 关于收件人的表,群发彩信时收件人地址就存在这里。
drm 彩信中媒体文件权限信息。
pdu 彩信的基本信息。
part 彩信的每个媒体文件(比如彩信有多少个音频,图片或视频)。
pending_msgs 表用于存储待发送或下载的短信与彩信,原文注释:This table stores the queue of messages to be sent/downloaded。
sr_pending 同样是原文注释:This table is used by the SMS dispatcher to hold pending delivery status report intents.
以words开头的四张表存储了短彩信中的单词,这是搜索时使用, 针对短彩信的内容进行通过FTS3算法分词后再写入这些表的,这里的words表是一张虚表,
其它三张是临时表。
threads 会话表,就是converstationList界面展示所用到的表。
sms 短信表
canonical_addresses 和联系人有关的表 在threads表的recipient_ids字段 存放的是参与此次对话的联系人的id,但是这个id并不是Contacts应用里面的id, 而是canonical_addresses表 的id,这就是canonical_addresses 表格的作用,这里有点绕,不过好在对我们的影响不是很大。
我们最关心的是 sms表, pdu表,part表和 threads表,顺带要看的 addr表、canonical_addresses表, 特殊情况下要知道 words表、pending_msgs表和raw表和 sr_pending表。这些表每个字段是什么意思可以查看 Telephony.java (frameworks\base\core\java\android\provider),这里详细说明了每个字段是做什么的,所以本文不详述了。下面看对应的代码,路径在packages\providers\TelephonyProvider\src\com\android\providers\telephony,包括
Smsprovider.java 负责sms表的增 删 改 查 content://sms
MmsProvider.java 负责part pdu表的增 删 改 查 content://mms
MmsSmsProviders.java 主要负责threads的表的增 删 改 查 content://mms-sms/
MmssmsDateBaseHelper.java 建表、建索引和创建触发器的sql语句都在这里,什么都有了。
public void onCreate(SQLiteDatabase db) {
createMmsTables(db);
createSmsTables(db);
createCommonTables(db);
createCommonTriggers(db);
createMmsTriggers(db);
createWordsTables(db);
createIndices(db);
}
sms表,pdu表、part表和threads表这几个表是怎么联系起来的呢?threads表就是一张用来显示的表,信息的主界面那个列表就是根据threads表的内容显示的。真正的数据 是存放sms表、pdu表和part表里,threads表里只保存了每个会话的最近一条信息内容。
以短信为例,当第收到或发送短信时,首先看是否有相同联系 人的会话在在数据库,没有则通过Telephony.java内部类Threads.java的getOrCreateThreadId()方法先向threads表写一条记录(这个地方不小心上源码的当了,明 明是一个insert的操作,去放在了MmsSmsProviders.java的query方法里面,习惯思维害人不浅),写完后暂时不管threads表了,将短信的收发联系人和短信内容、时间等信息写入到sms表,然后通过触发器去更新threads中的信息。通过代码可以发现threads表的大部分的操作都是利用触发器完成的,彩信保存原理与短信类似,只不过彩信还要先写入pdu表,再写入part表。删除信息的时候流程倒过来,先删除sms表、pdu表和part表的信息,再删除reads表的信息。
关于mms存储的基本知识差不多就这些,细节还是要自己体验的,多多Debug自然就清楚了。
PS: 在第一篇文章里说过,android的信息是写数据库,信息的内容都解码出来后再写入数据库,而WinCE平台下通常是写文件保存整个信息的,两种方法各有利弊吧。写数据库的,提取相应字段信息、查看消息内容是非常方便的,但是如果是转发或重发,是必须要重新打pdu包的;写文件的上述操作是方便了,可查看 的时候你要再解码一次。两种没有好坏之分都可以,根据需要做个选择吧。