转载声明:文章来源:https://blog.csdn.net/sjz4860402/article/details/41048287
在看这个模块前,个人认为先了解一下短信的数据存储会容易一些。首先,短信信息肯定是存储在数据库中,那么这些数据库中都有些什么表?存储的是什么东西呢?我们可以把手机连上电脑,打开eclipse,用DDMS模式查看一下手机里的文件。如下:
短信模块的数据库就是图中的mmssms.db文件,点击右上角的导出功能,把db文件导到电脑中,用Navicat for SQLite软件查看这个db文件。这个db数据库文件中包含的表如下:
其中,sms是存放短信的表,pdu和part是存放彩信的表,canonical_addresses是存放手机号码的表,threads是存放会话信息的表,pending_msgs用于存储待发送或下载的短信与彩信的表(有待证实),使用pdu中的触发器进行插入和删除。raw表用于存储接收中的长短信或分段彩信通知。drm用于彩信权限管理。words开头的表存储了短彩信中的单词,用于搜索时使用。attachments、rate、sr_pending表作用未知。android_metadata表存储的是语言信息,就一条记录。
重点看一下sms,pdu,part,threads四个表。(后面补上后三个表)
下面是sms表,表中的属性是:
_id: 主键,唯一
thread_id: 会话id(和thread表关联),这个会话是指:我跟A互发短信,这是一个会话;我跟B互发短信,这是一个会话;我和A,B群发短信,这是另一个会话。会话包含了所有的短信信息(多条),我们手机短信列表里的每一项就是一个会话。如下图中的,三个thread_id都为1,表明这三个消息都是属于同一个会话的,两个thread_id为4,这两个是同属于一个会话。
address: 地址,也就是收件人的手机号码。如下图,有个加号的+8618521564884是别人发过来的短信,没有加号的是从本机发送过去的短信。Null的是编辑的草稿信息
person: 联系人地址,(跟通讯录有关)
data: 发送短信时间
data_sent: 接受短信时间
protecd: 协议,分为: 0 SMS_RPOTO, 1 MMS_PROTO
read: 是否阅读 0未读, 1已读
status: 状态 -1接收,0 complete, 64 pending, 128 failed
type: ALL=0; 表示所有短信
INBOX=1; 表示这个短信属于收件箱
SENT=2; 表示短信已经发送成功
DRAFT=3; 表示短信属于草稿箱
OUTBOX=4; 表示短信属于发件箱(正在发送)
FAILED=5; 表示发送失败
QUEUED=6; 表示短信在待发送队列中
这里的type 很重要,一个信息的type在发送或者接收的整个过程中会不断的被改变,以区分这个信息处于什么阶段。
body: 短信内容
service_center: 短信服务中心号码编号
subject: 短信的主题
reply_path_present: TP-Reply-Path
locked: 此条短信是否已由用户锁定,0-未锁定,1-已锁定
send: 用于指明该消息是否已被用户看到(非阅读,点开会话列表即可,不用打开会话),仅对收到的消息有用
下面是thread表,表中的属性为:
_id: 主键,唯一
date_sent: 会话最新更新时间
message_count: 当前会话所包含的消息数量
recipient_ids: 接收者(canonical_addresses表的id)列表,所有接收者以空格隔开
snippet: 最新更新的消息的内容(彩信为主题,短信为正文)
read: 是否有未读信息:0-未读,1-已读
type: 会话类型,0-普通会话(只有一个接收者),1-广播会话(多个接收者)
has_attachment: 是否有附件:0-无,1-有
知道了短信数据库中的表结构,那么怎样操作数据库呢?
我们先看一下数据库的创建是在什么地方,找到
packages/providers/TelephonyProvider/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
这个MmsSmsDatabaseHelper继承了SQLiteOpenHelper类,用来创建数据库和数据表。其中创建sms表的代码如下:
private void createSmsTables(SQLiteDatabase db) {
// N.B.: Whenever the columns here are changed, the columns in
// {@ref MmsSmsProvider} must be changed to match.
db.execSQL("CREATE TABLE sms (" +
"_id INTEGER PRIMARY KEY," +
"thread_id INTEGER," +
"address TEXT," +
/// M: Code analyze 016, unknown, new column in sms table.
"m_size INTEGER," +
"person INTEGER," +
"date INTEGER," +
"date_sent INTEGER DEFAULT 0," +
"protocol INTEGER," +
"read INTEGER DEFAULT 0," +
"status INTEGER DEFAULT -1," + // a TP-Status value
// or -1 if it
// status hasn't
// been received
"type INTEGER," +
"reply_path_present INTEGER," +
"subject TEXT," +
"body TEXT," +
"service_center TEXT," +
"locked INTEGER DEFAULT 0," +
/// M: Code analyze 015, new feature, support for gemini.
"sim_id INTEGER DEFAULT -1," +
"error_code INTEGER DEFAULT 0," +
"seen INTEGER DEFAULT 0," +
/// M: Add for ip message
"ipmsg_id INTEGER DEFAULT 0," +
/// M: for ct new feature of concatenated sms @{
// ref_id: the unique id for specific contatenated sms
// total_len: the total parts of concatenated sms
// rec_len: the number of parts that have received
"ref_id INTEGER," +
"total_len INTEGER," +
"rec_len INTEGER" +
/// M: @}
");");
/**
* This table is used by the SMS dispatcher to hold
* incomplete partial messages until all the parts arrive.
*/
db.execSQL("CREATE TABLE raw (" +
"_id INTEGER PRIMARY KEY," +
"date INTEGER," +
"reference_number INTEGER," + // one per full message
"count INTEGER," + // the number of parts
"sequence INTEGER," + // the part number of this message
"destination_port INTEGER," +
"address TEXT," +
/// M: Code analyze 015, new feature, support for gemini.
"sim_id INTEGER DEFAULT 0," +
"pdu TEXT," +
/// M: for ct new feature of concatenated sms @{
"recv_time INTEGER," +
"upload_flag INTEGER" +
/// M: @}
");"); // the raw PDU for this part
db.execSQL("CREATE TABLE attachments (" +
"sms_id INTEGER," +
"content_url TEXT," +
"offset INTEGER);");
/**
* This table is used by the SMS dispatcher to hold pending
* delivery status report intents.
*/
db.execSQL("CREATE TABLE sr_pending (" +
"reference_number INTEGER," +
"action TEXT," +
"data TEXT);");
}
既然找到了创建数据库的相关类,那么我们可以看看它在哪里被调用的。这里可以追溯到SmsProvider。如下:
@Override
public Cursor query(Uri url, String[] projectionIn, String selection,
String[] selectionArgs, String sort) {
MmsLog.d(TAG, "query begin, uri = " + url + ", selection = " + selection);
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
// Generate the body of the query.
int match = sURLMatcher.match(url);
switch (match) {
case SMS_ALL:
constructQueryForBox(qb, Sms.MESSAGE_TYPE_ALL);
break;
case SMS_UNDELIVERED:
constructQueryForUndelivered(qb);
break;
case SMS_FAILED:
constructQueryForBox(qb, Sms.MESSAGE_TYPE_FAILED);
break;
case SMS_QUEUED:
constructQueryForBox(qb, Sms.MESSAGE_TYPE_QUEUED);
break;
case SMS_INBOX:
constructQueryForBox(qb, Sms.MESSAGE_TYPE_INBOX);
break;
case SMS_SENT:
constructQueryForBox(qb, Sms.MESSAGE_TYPE_SENT);
break;
case SMS_DRAFT:
constructQueryForBox(qb, Sms.MESSAGE_TYPE_DRAFT);
break;
case SMS_OUTBOX:
constructQueryForBox(qb, Sms.MESSAGE_TYPE_OUTBOX);
break;
case SMS_ALL_ID:
qb.setTables(TABLE_SMS);
qb.appendWhere("(_id = " + url.getPathSegments().get(0) + ")");
break;
。。。。
}
}
可以看到,SmsProvider是通过解析uri来决定查询什么类型的短信数据,如:收件箱,发件箱,草稿箱等。
ContentProvider(内容提供器)用来管理和共享数据库。对于ContentProvider,这里有一篇文章可以了解一下ContentProvider,ContentResolver,uri三者之间的关系。
sms中有关的uri如下: 对应以上 SmsProvider中的Sms.MESSAGE_TYPE_FAILED,Sms.MESSAGE_TYPE_QUEUED,Sms.MESSAGE_TYPE_DRAFT等等。
public final static String SMS_URI_ALL = "content://sms/"; //0 表示所有短信
public final static String SMS_URI_INBOX = "content://sms/inbox";//1 收件箱
public final static String SMS_URI_SEND = "content://sms/sent";//2 已发送
public final static String SMS_URI_DRAFT = "content://sms/draft";//3 草稿
public final static String SMS_URI_OUTBOX = "content://sms/outbox";//4 发件箱
public final static String SMS_URI_FAILED = "content://sms/failed";//5 发送失败
public final static String SMS_URI_QUEUED = "content://sms/queued";//6 待发送列表
比如使用了ContentProvider来查询发件箱的所有信息时,需要提供的地址就是:
content://sms/inbox
短信模块的ContentProvider提供了三个子类:SmsProvider、MmsProvider、MmsSmsProvider,以及一个辅助类Telephony。其中,SmsProvider用于短信相关数据的存取,MmsProvider用于彩信相关数据的存取,MmsSmsProvider则用于短彩信通用数据的存取,如会话信息、接收者、草稿(公共属性)等。Telephony则提供了一系列Uri、常量字符串列名数组、方法以便用户使用这三个ContentProvider。Telephony里面定义了很多的内部类:sms,mms....而 sms,mms里面又定义了Outbox,inbox,draft等内部类。分别提供对短彩信数据库的各种操作。详情参考源码。
————————————————
版权声明:本文为CSDN博主「谁的影子」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/sjz4860402/article/details/41048287
帖子还没人回复快来抢沙发