关于Android中获取短信息会话(threads)表中的信息

来源:互联网 发布:4gip网络加速器 费用 编辑:程序博客网 时间:2024/05/21 10:46

最近因为项目的需要,需要处理android手机中的短信,在PC端读取手机上的短信信息。那么首先需要得到手机上的会话信息进行概要显示。

网上关于如何获取会话信息的文章不少,我也是以它们为参考。但是在测试中发现一些问题,以及处理的方法,记录如下:

一、刚开始根据网上的文章,使用sql注释的方式直接操作threads表。
参考文章地址:
http://blog.csdn.net/vennl/article/details/7079135
http://www.cnblogs.com/GnagWang/archive/2011/01/06/1929075.html

使用的代码片段:

String SMS_URI_ALL = "content://sms/";cursor = cr.query(Uri.parse(SMS_URI_ALL),        new String[]{"* from threads order by date desc--"}, null, null, null);

使用这段代码,开始视乎一切正常。在很多机器上测试也OK。但是在小米note3上会抛出异常:
E/AndroidRuntime(26724): android.database.sqlite.SQLiteException: near “FROM”: syntax error (code 1): , while compiling:
SELECT FROM sms
WHERE ((thread_id IN (select _id from threads where private_addr_ids is NULL AND sp_type=0)) AND (deleted=0)) ORDER BY date DESC

看异常提示发现 FROM后面的*号不见了。暂时还不知什么原因,或者是红米做了什么限制。

二、这时开始换第二种方法.
参考文章:
http://www.tuicool.com/articles/fyeEVb

private static final String[] PROJECTION = new String[]{        //cursor 查询 需要_id        "sms.thread_id AS _id",        "sms.body AS snippet",        "groups.msg_count AS msg_count",        "sms.address AS address",        "sms.date AS date"    };    //查询短信数据    private void startQuery() {        /**         * 查询会话数据         * token Sql id 查询结果的唯一标识  _ID          * cookie  用来传递数据  通常VIEW         * uri  指定查询数据的地址         * projection   相当于SQL查询中 select 中的字段           * selection    相当于SQL查询中 where id = ?          * selectionArgs ?         * orderBy      排序         */        Uri uri = Uri.parse("content://sms/conversations/");        queryHandler.startQuery(0, null, uri, PROJECTION, null, null, " date DESC");    }

但是使用这段代码会有错误提示:
no such column: sms.thread_id (code 1): , while compiling:

SELECT sms.thread_id AS _id, sms.body AS snippet, groups.msg_count AS msg_count, sms.address AS address, sms.date AS date

FROM
(SELECT thread_id AS tid, date * 1000 AS normalized_date, NULL AS error_code, ct_t, recipient_cc_ids, msg_box, NULL AS reply_path_present, v, sub, rr, NULL AS status, retr_txt_cs, ct_l, ct_cls, NULL AS dest_port, phone_id, NULL AS subject, NULL AS format_data, _id, m_size, NULL AS type, exp, sub_cs, NULL AS address, st, NULL AS person, tr_id, read, resp_st, date, NULL AS body, m_id, date_sent, recipient_bcc_ids, NULL AS sms_pdu, pri, NULL AS expiry, m_type, thread_id, read_status, d_rpt, locked, NULL AS service_date, NULL AS priority, resp_txt, rpt_a, retr_st, m_cls, NULL AS service_center
FROM pdu_restricted
WHERE ((msg_box != 3 AND (m_type = 128 OR m_type = 132 OR m_type = 160 OR m_type = 161 OR m_type = 130)))
GROUP BY thread_id
HAVING date = MAX(date)
UNION
SELECT thread_id AS tid, date * 1 AS normalized_date, error_code, NULL AS ct_t, recipient_cc_ids, NULL AS msg_box, reply_path_present, NULL AS v, NULL AS sub, NULL AS rr, status, NULL AS retr_txt_cs, NULL AS ct_l, NULL AS ct_cls, dest_port, phone_id, subject, format_data, _id, NULL AS m_size, type, NULL AS exp, NULL AS sub_cs, address, NULL AS st, person, NULL AS tr_id, read, NULL AS resp_st, date, body, NULL AS m_id, date_sent, recipient_bcc_ids, sms_pdu, NULL AS pri, expiry, NULL AS m_type, thread_id, NULL AS read_status, NULL AS d_rpt, locked, service_date, priority, NULL AS resp_txt, NULL AS rpt_a, NULL AS retr_st, NULL AS m_cls, service_center
FROM sms_restricted
WHERE ((type != 3))
GROUP BY thread_id
HAVING date = MAX(date))
GROUP BY tid
HAVING normalized_date = MAX(normalized_date)
ORDER BY date DESC

我们从提示中也能看出android是如何读取短信数据库的。

根据错误提示,修改代码如下:

String[] PROJECTION = new String[]{        "thread_id"};Uri uri = Uri.parse( "content://mms-sms/conversations" );cursor = cr.query( uri, PROJECTION , null ,null, "date DESC" );

然后一切似乎都OK, 不过后来发现在mate 9 和部分moto机器上读不出会话信息。

三、终极解决方案,直接找源码
直接参考android中关于这部分的源码实现。
https://github.com/android/platform_packages_apps_mms

使用的代码片段如下:

Uri sAllThreadsUri =        Threads.CONTENT_URI.buildUpon().appendQueryParameter("simple", "true").build();String[] ALL_THREADS_PROJECTION = {        Threads._ID, Threads.DATE, Threads.MESSAGE_COUNT, Threads.RECIPIENT_IDS,        Threads.SNIPPET, Threads.SNIPPET_CHARSET, Threads.READ, Threads.ERROR,        Threads.HAS_ATTACHMENT};cursor = cr.query( sAllThreadsUri, ALL_THREADS_PROJECTION , null ,null, "date DESC" );

和第二种方法的区别是多了参数simple=true

这种方式在现在手头有的机型中测试正常。

1 0
原创粉丝点击