Android短信彩信开发手记(一):数据库相关

参考:

http://gnibre.iteye.com/blog/558031

http://www.cnblogs.com/qinglong1983/

http://jackyear.is-programmer.com/


短信 sms

文件 /data/data/com.android.providers.telephony/databases/mmssms.db
这个数据库有13张表,sms表存了短信信息。

短信收件箱对应的URI是content://sms/inbox

很简单吧,就是sms短信,然后inbox收件箱,类似,短信里面的URI分别是

content://sms/

content://sms/inbox

content://sms/sent

content://sms/draft

content://sms/outbox

content://sms/failed

content://sms/queued


android.provider.Telephony:

    /** 
      * The thread ID of the message 
      * <P>Type: INTEGER</P> 
      */  
     public static final String THREAD_ID = "thread_id";  
      
     /** 
      * The address of the other party 
      * <P>Type: TEXT</P> 
      */  
     public static final String ADDRESS = "address";  
      
     /** 
      * The person ID of the sender 
      * <P>Type: INTEGER (long)</P> 
      */  
     public static final String PERSON_ID = "person";  
      
     /** 
      * The date the message was sent 
      * <P>Type: INTEGER (long)</P> 
      */  
     public static final String DATE = "date";  
      
     /** 
      * The protocol identifier code 
      * <P>Type: INTEGER</P> 
      */  
     public static final String PROTOCOL = "protocol";  
      
     /** 
      * Has the message been read 
      * <P>Type: INTEGER (boolean)</P> 
      */  
     public static final String READ = "read";  
      
      
     /** 
      * The TP-Status value for the message, or -1 if no status has 
      * been received 
      */  
     public static final String STATUS = "status";  
    us 举例:  
     public static final int STATUS_NONE = -1;  
     public static final int STATUS_COMPLETE = 0;  
     public static final int STATUS_PENDING = 64;  
     public static final int STATUS_FAILED = 128;  
      
    /** 
      * The type of the message 
      * <P>Type: INTEGER</P> 
      */  
     public static final String TYPE = "type";  
     举例  
     public static final int MESSAGE_TYPE_ALL    = 0;  
     public static final int MESSAGE_TYPE_INBOX  = 1;  
     public static final int MESSAGE_TYPE_SENT   = 2;  
     public static final int MESSAGE_TYPE_DRAFT  = 3;  
     public static final int MESSAGE_TYPE_OUTBOX = 4;  
     public static final int MESSAGE_TYPE_FAILED = 5; // for failed outgoing messages  
     public static final int MESSAGE_TYPE_QUEUED = 6; // for messages to send later  
      
      
     /** 
      * Whether the <code>TP-Reply-Path</code> bit was set on this message 
      * <P>Type: BOOLEAN</P> 
      */  
     public static final String REPLY_PATH_PRESENT = "reply_path_present";  
      
     /** 
      * The subject of the message, if present 
      * <P>Type: TEXT</P> 
      */  
     public static final String SUBJECT = "subject";  
      
      
     /** 
      * The body of the message 
      * <P>Type: TEXT</P> 
      */  
     public static final String BODY = "body";  
      
      
     /** 
      * The service center (SC) through which to send the message, if present 
      * <P>Type: TEXT</P> 
      */  
     public static final String SERVICE_CENTER = "service_center";  
      
      
      
     /** 
      * Has the message been locked? 
      * <P>Type: INTEGER (boolean)</P> 
      */  
     public static final String LOCKED = "locked";  
      
    **  
      * The id of the sender of the conversation, if present  
      * <P>Type: INTEGER (reference to item in content://contacts/people)</P>  
      */  
     public static final String PERSON = "person";  
_id               一个自增字段,从1开始
thread_id    序号,同一发信人的id相同
address      发件人手机号码
person        联系人列表里的序号,陌生人为null (不稳定无法获取联系人ID)
date            发件日期
protocol      协议,分为: 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;
body                     短信内容
service_center     短信服务中心号码编号
subject                  短信的主题
reply_path_present     TP-Reply-Path

locked  



Url中content://sms 替换成content://sms/ 也成功,但是其它url时程序报错,比如content://sms/inbox

看了一下android的源代码,sms支持的协议有:


sURLMatcher.addURI("sms", null, SMS_ALL);
sURLMatcher.addURI("sms", "#", SMS_ALL_ID);
sURLMatcher.addURI("sms", "inbox", SMS_INBOX);
sURLMatcher.addURI("sms", "inbox/#", SMS_INBOX_ID);
sURLMatcher.addURI("sms", "sent", SMS_SENT);
sURLMatcher.addURI("sms", "sent/#", SMS_SENT_ID);
sURLMatcher.addURI("sms", "draft", SMS_DRAFT);
sURLMatcher.addURI("sms", "draft/#", SMS_DRAFT_ID);
sURLMatcher.addURI("sms", "outbox", SMS_OUTBOX);
sURLMatcher.addURI("sms", "outbox/#", SMS_OUTBOX_ID);
sURLMatcher.addURI("sms", "undelivered", SMS_UNDELIVERED);
sURLMatcher.addURI("sms", "failed", SMS_FAILED);
sURLMatcher.addURI("sms", "failed/#", SMS_FAILED_ID);
sURLMatcher.addURI("sms", "queued", SMS_QUEUED);
sURLMatcher.addURI("sms", "conversations", SMS_CONVERSATIONS);
sURLMatcher.addURI("sms", "conversations/*", SMS_CONVERSATIONS_ID);
sURLMatcher.addURI("sms", "raw", SMS_RAW_MESSAGE);
sURLMatcher.addURI("sms", "attachments", SMS_ATTACHMENT);
sURLMatcher.addURI("sms", "attachments/#", SMS_ATTACHMENT_ID);
sURLMatcher.addURI("sms", "threadID", SMS_NEW_THREAD_ID);
sURLMatcher.addURI("sms", "threadID/*", SMS_QUERY_THREAD_ID);
sURLMatcher.addURI("sms", "status/#", SMS_STATUS_ID);
sURLMatcher.addURI("sms", "sr_pending", SMS_STATUS_PENDING);
sURLMatcher.addURI("sms", "sim", SMS_ALL_SIM);
sURLMatcher.addURI("sms", "sim/#", SMS_SIM);


--------------------------------------------------------------------------------

其中,delete方法中支持的协议为:

SMS_ALL               根据参数中的条件删除sms表数据
SMS_ALL_ID         根据_id删除sms表数据
SMS_CONVERSATIONS_ID     根据thread_id删除sms表数据,可以带其它条件
SMS_RAW_MESSAGE              根据参数中的条件删除 raw表
SMS_STATUS_PENDING         根据参数中的条件删除 sr_pending表
SMS_SIM                                 从Sim卡上删除数据


试一下SMS_CONVERSATIONS_ID:"
在eclipse中的Emulator Control中,以13800给模拟器发送三条数据,然后以13900发送一条       
this.getContentResolver().delete(Uri.parse("content://sms/conversations/3"), "_id=?", new String[]{"5"});        
成功删除一条数据。  

在数据库中每个发送者的thread_id虽然一样,但不是固定的,如果把一个发送者的全部数据删除掉,       
然后换一个新号码发送短信时,thread_id是以数据库中最大的id+1赋值的。  


--------------------------------------------------------------------------------

update支持的协议有很多:

SMS_RAW_MESSAGE   
SMS_STATUS_PENDING   
SMS_ALL   
SMS_FAILED   
SMS_QUEUED   
SMS_INBOX   
SMS_SENT   
SMS_DRAFT   
SMS_OUTBOX   
SMS_CONVERSATIONS   
SMS_ALL_ID   
SMS_INBOX_ID   
SMS_FAILED_ID   
SMS_SENT_ID   
SMS_DRAFT_ID   
SMS_OUTBOX_ID   
SMS_CONVERSATIONS_ID   
SMS_STATUS_ID   


以SMS_INBOX_ID测试一下:   
ContentValues cv = new ContentValues();   
cv.put("thread_id", "2");   
cv.put("address", "00000");   
cv.put("person", "11");   
cv.put("date", "11111111");   
this.getContentResolver().update(Uri.parse("content://sms/inbox/4"), cv, null, null);   
太强了,连thread_id都可以修改。  


--------------------------------------------------------------------------------

insert支持的协议:

SMS_ALL   
SMS_INBOX   
SMS_FAILED   
SMS_QUEUED   
SMS_SENT   
SMS_DRAFT   
SMS_OUTBOX   
SMS_RAW_MESSAGE   
SMS_STATUS_PENDING   
SMS_ATTACHMENT   
SMS_NEW_THREAD_ID   


向sms表插入数据时,type是根据协议来自动设置,   
如果传入的数据中没有设置date时,自动设置为当前系统时间;非SMS_INBOX协议时,read标志设置为1   
SMS_INBOX协议时,系统会自动查询并设置PERSON   
threadId为null或者0时,系统也会自动设置  


一直为造不了"发送失败"的邮件而发愁,现在来做一个:   
content://sms/failed  


ContentValues cv = new ContentValues();   
cv.put("_id", "99");   
cv.put("thread_id", "0");   
cv.put("address", "9999");   
cv.put("person", "888");   
cv.put("date", "9999");
cv.put("protocol", "0");
cv.put("read", "1");
cv.put("status", "-1");
//cv.put("type", "0");
cv.put("body", "@@@@@@@@@");

this.getContentResolver().insert(Uri.parse("content://sms/failed"), cv);
type被设置成了5,thread_id设置为1




彩信。

1、pdu表
    mmssms.db库中的pdu表存储了彩信标题、彩信接收时间和彩信ID等信息,其中“_id”是主键,唯一标识了一个条彩信。
    /** 
     * Base columns for tables that contain MMSs. 
     */  
    public interface BaseMmsColumns extends BaseColumns {  
      
        public static final int MESSAGE_BOX_ALL    = 0;  
        public static final int MESSAGE_BOX_INBOX  = 1;  
        public static final int MESSAGE_BOX_SENT   = 2;  
        public static final int MESSAGE_BOX_DRAFTS = 3;  
        public static final int MESSAGE_BOX_OUTBOX = 4;  
      
        /** 
         * The date the message was sent. 
         * <P>Type: INTEGER (long)</P> 
         */  
        public static final String DATE = "date";  
      
        /** 
         * The box which the message belong to, for example, MESSAGE_BOX_INBOX. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String MESSAGE_BOX = "msg_box";  
      
        /** 
         * Has the message been read. 
         * <P>Type: INTEGER (boolean)</P> 
         */  
        public static final String READ = "read";  
      
        /** 
         * The Message-ID of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String MESSAGE_ID = "m_id";  
      
        /** 
         * The subject of the message, if present. 
         * <P>Type: TEXT</P> 
         */  
        public static final String SUBJECT = "sub";  
      
        /** 
         * The character set of the subject, if present. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String SUBJECT_CHARSET = "sub_cs";  
      
        /** 
         * The Content-Type of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String CONTENT_TYPE = "ct_t";  
      
        /** 
         * The Content-Location of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String CONTENT_LOCATION = "ct_l";  
      
        /** 
         * The address of the sender. 
         * <P>Type: TEXT</P> 
         */  
        public static final String FROM = "from";  
      
        /** 
         * The address of the recipients. 
         * <P>Type: TEXT</P> 
         */  
        public static final String TO = "to";  
      
        /** 
         * The address of the cc. recipients. 
         * <P>Type: TEXT</P> 
         */  
        public static final String CC = "cc";  
      
        /** 
         * The address of the bcc. recipients. 
         * <P>Type: TEXT</P> 
         */  
        public static final String BCC = "bcc";  
      
        /** 
         * The expiry time of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String EXPIRY = "exp";  
      
        /** 
         * The class of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String MESSAGE_CLASS = "m_cls";  
      
        /** 
         * The type of the message defined by MMS spec. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String MESSAGE_TYPE = "m_type";  
      
        /** 
         * The version of specification that this message conform. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String MMS_VERSION = "v";  
      
        /** 
         * The size of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String MESSAGE_SIZE = "m_size";  
      
        /** 
         * The priority of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String PRIORITY = "pri";  
      
        /** 
         * The read-report of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String READ_REPORT = "rr";  
      
        /** 
         * Whether the report is allowed. 
         * <P>Type: TEXT</P> 
         */  
        public static final String REPORT_ALLOWED = "rpt_a";  
      
        /** 
         * The response-status of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String RESPONSE_STATUS = "resp_st";  
      
        /** 
         * The status of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String STATUS = "st";  
      
        /** 
         * The transaction-id of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String TRANSACTION_ID = "tr_id";  
      
        /** 
         * The retrieve-status of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String RETRIEVE_STATUS = "retr_st";  
      
        /** 
         * The retrieve-text of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String RETRIEVE_TEXT = "retr_txt";  
      
        /** 
         * The character set of the retrieve-text. 
         * <P>Type: TEXT</P> 
         */  
        public static final String RETRIEVE_TEXT_CHARSET = "retr_txt_cs";  
      
        /** 
         * The read-status of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String READ_STATUS = "read_status";  
      
        /** 
         * The content-class of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String CONTENT_CLASS = "ct_cls";  
      
        /** 
         * The delivery-report of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String DELIVERY_REPORT = "d_rpt";  
      
        /** 
         * The delivery-time-token of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String DELIVERY_TIME_TOKEN = "d_tm_tok";  
      
        /** 
         * The delivery-time of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String DELIVERY_TIME = "d_tm";  
      
        /** 
         * The response-text of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String RESPONSE_TEXT = "resp_txt";  
      
        /** 
         * The sender-visibility of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String SENDER_VISIBILITY = "s_vis";  
      
        /** 
         * The reply-charging of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String REPLY_CHARGING = "r_chg";  
      
        /** 
         * The reply-charging-deadline-token of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String REPLY_CHARGING_DEADLINE_TOKEN = "r_chg_dl_tok";  
      
        /** 
         * The reply-charging-deadline of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String REPLY_CHARGING_DEADLINE = "r_chg_dl";  
      
        /** 
         * The reply-charging-id of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String REPLY_CHARGING_ID = "r_chg_id";  
      
        /** 
         * The reply-charging-size of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String REPLY_CHARGING_SIZE = "r_chg_sz";  
      
        /** 
         * The previously-sent-by of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String PREVIOUSLY_SENT_BY = "p_s_by";  
      
        /** 
         * The previously-sent-date of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String PREVIOUSLY_SENT_DATE = "p_s_d";  
      
        /** 
         * The store of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String STORE = "store";  
      
        /** 
         * The mm-state of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String MM_STATE = "mm_st";  
      
        /** 
         * The mm-flags-token of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String MM_FLAGS_TOKEN = "mm_flg_tok";  
      
        /** 
         * The mm-flags of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String MM_FLAGS = "mm_flg";  
      
        /** 
         * The store-status of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String STORE_STATUS = "store_st";  
      
        /** 
         * The store-status-text of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String STORE_STATUS_TEXT = "store_st_txt";  
      
        /** 
         * The stored of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String STORED = "stored";  
      
        /** 
         * The totals of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String TOTALS = "totals";  
      
        /** 
         * The mbox-totals of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String MBOX_TOTALS = "mb_t";  
      
        /** 
         * The mbox-totals-token of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String MBOX_TOTALS_TOKEN = "mb_t_tok";  
      
        /** 
         * The quotas of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String QUOTAS = "qt";  
      
        /** 
         * The mbox-quotas of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String MBOX_QUOTAS = "mb_qt";  
      
        /** 
         * The mbox-quotas-token of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String MBOX_QUOTAS_TOKEN = "mb_qt_tok";  
      
        /** 
         * The message-count of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String MESSAGE_COUNT = "m_cnt";  
      
        /** 
         * The start of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String START = "start";  
      
        /** 
         * The distribution-indicator of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String DISTRIBUTION_INDICATOR = "d_ind";  
      
        /** 
         * The element-descriptor of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String ELEMENT_DESCRIPTOR = "e_des";  
      
        /** 
         * The limit of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String LIMIT = "limit";  
      
        /** 
         * The recommended-retrieval-mode of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String RECOMMENDED_RETRIEVAL_MODE = "r_r_mod";  
      
        /** 
         * The recommended-retrieval-mode-text of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String RECOMMENDED_RETRIEVAL_MODE_TEXT = "r_r_mod_txt";  
      
        /** 
         * The status-text of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String STATUS_TEXT = "st_txt";  
      
        /** 
         * The applic-id of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String APPLIC_ID = "apl_id";  
      
        /** 
         * The reply-applic-id of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String REPLY_APPLIC_ID = "r_apl_id";  
      
        /** 
         * The aux-applic-id of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String AUX_APPLIC_ID = "aux_apl_id";  
      
        /** 
         * The drm-content of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String DRM_CONTENT = "drm_c";  
      
        /** 
         * The adaptation-allowed of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String ADAPTATION_ALLOWED = "adp_a";  
      
        /** 
         * The replace-id of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String REPLACE_ID = "repl_id";  
      
        /** 
         * The cancel-id of the message. 
         * <P>Type: TEXT</P> 
         */  
        public static final String CANCEL_ID = "cl_id";  
      
        /** 
         * The cancel-status of the message. 
         * <P>Type: INTEGER</P> 
         */  
        public static final String CANCEL_STATUS = "cl_st";  
      
        /** 
         * The thread ID of the message 
         * <P>Type: INTEGER</P> 
         */  
        public static final String THREAD_ID = "thread_id";  
      
        /** 
         * Has the message been locked? 
         * <P>Type: INTEGER (boolean)</P> 
         */  
        public static final String LOCKED = "locked";  
    }  

2、part表
    mmssms.db库中的part表存储了彩信内容(文本、音乐、图象)的文件名(即上面将的app_parts下面的文件名)、文件类型信息。
    其中“mid”对应着pdu表中的“_id”,“ct”是文件类型,“_data”是存储路径。

3 。 彩信文件读取

      彩信附件文件的地址存储在mmssms.db的part表的_data字段,形如“/data/data/com.android.providers.telephony/app_parts/PART_1262693697763”,但在应用中读取彩信附件时,这个字段基本没什么用,因为不能直接读取这个文件。读取同样要通过ContentProvider,URI为“content://mms/part”,该URI就是对应着part表。可以使用下列代码段来读取文件:
String selection = new String("mid='" + key + "'");//这个key就是pdu里面的_id。
Cursor cur = getContentResolver().query(Uri.parse("content://mms/part"), null, selection, null, null);

        if (cur.moveToFirst())
            do {
                    int _partID = cur.getInt(cur.getColumnIndex("_id"));
                    String partID = String.valueOf(_partID);
                    Uri partURI = Uri.parse("content://mms/part/" + partID);
                   
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    InputStream is = null;

                    try {
                        is = getContentResolver().openInputStream(partURI);
                        byte[] buffer = new byte[256];
                        int len = is.read(buffer);
                        while (len >= 0)
                        {
                            baos.write(buffer, 0, len);
                            len = is.read(buffer);
                        }
                    } catch (IOException e) {
                    } finally {
                        if (is != null) {
                            try {
                                is.close();
                            } catch (IOException e) {

                            }
                        }
                    }
                    }
    这里得到的baos,就是附件文件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值