短信模块(一)

来源:互联网 发布:world of tank mac 编辑:程序博客网 时间:2023/11/29 02:45

最近在学习短信模块,写点东西以免以后又忘记了。

在看这个模块前,个人认为先了解一下短信的数据存储会容易一些。首先,短信信息肯定是存储在数据库中,那么这些数据库中都有些什么表?存储的是什么东西呢?我们可以把手机连上电脑,打开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等内部类。分别提供对短彩信数据库的各种操作。详情参考源码。


0 0
原创粉丝点击