短信 threads 表 , 查询 更新

短信 thread 表 以及 在Telephony.Threads

1.表中字段

_id INTEGER PRIMARY_KEY 主键ID 系统生成

date INTEGER The date at which the thread was created. 日期

message_count INTEGER The message count of the thread. 该会话的短信总条数

recipient_ids TEXT canonical_addresses的主键 FK

snippet TEXT The snippet of the latest message in the thread. 在最前面显示的短信

snippet_cs INTEGER The charset of the snippet.

read INTEGER Indicates whether all messages of the thread have been read. 已读为1,未读为0

type INTEGER Type of the thread, either Threads.COMMON_THREAD or Threads.BROADCAST_THREAD. push的短信为0

error INTEGER Indicates whether there is a transmission error in the thread. 有错误为1,没有为0

has_attachment INTEGER Indicates whether this thread contains any attachments. 没有为1,有为0

2.

2.1.生成会话 id
//系统提供的方法
public static long getOrCreateThreadId(Context context, String recipient)

2.2查询threads 表

// 下面这个方法亲测可以查询出来 threads 表中的全部数据

getContentResolver().query(Uri.parse("content://sms/"), new String[]{"* from threads --"}, null, null, null);

//按照上面的方式 我试了一下查询sms 表,也是可以查询出来的

getContentResolver().query(Uri.parse("content://sms/"), new String[]{"* from threads --"}, null, null, null);

这个的原理应该是 后面的 – 将后面拼接的所有 sql 都注释掉了,所以只能执行前面的 selec * from 了

2.3其中短信模块刚进入时的会话列表界面其实也是 查询的 threads表进行显示的
在 com.android.sms.data.Conversation.java 中

android.provider.telephony.Thread;
//短信中对 uri做了参数处理

uri = Threads.CONTENT_URI.buildUpon().appendQueryParameter(“simple”,”true”).build();

// 其实直接用 thread URI 就可以查询出来,已验证
getContentResolver().query(Threads.CONTENT_URI, new String[]{“id, xx,xx,xx”}, null, null, “date desc”);

  1. 定义Telephony.MmsSms类。

Contains all MMS and SMS messages.

  1. 在Telephony.MmsSms中定义了一些URI常量。

public static final Uri CONTENT_URI = Uri.parse(“content://mms-sms/”);

public static final Uri CONTENT_CONVERSATIONS_URI = Uri.parse(
“content://mms-sms/conversations”);

public static final Uri CONTENT_FILTER_BYPHONE_URI = Uri.parse(
“content://mms-sms/messages/byphone”);

public static final Uri CONTENT_UNDELIVERED_URI = Uri.parse(
“content://mms-sms/undelivered”);

public static final Uri CONTENT_DRAFT_URI = Uri.parse(
“content://mms-sms/draft”);

public static final Uri CONTENT_LOCKED_URI = Uri.parse(
“content://mms-sms/locked”);

public static final Uri SEARCH_URI = Uri.parse(
“content://mms-sms/search”);

上面的方式是之前的, 发现网上很多说这个方式在一些机型上有问题,

发现很多东西还是要去看源码

  1. 首先是查询 threads 表的内容

源码位置: packages/providers/TelephonyProvider/src/com/android/providers/telephony/TelephonyBackupAgent.java
其实还有好多有用的方法可以在这个类中参考

1205    @VisibleForTesting
1206    static final Uri ALL_THREADS_URI =
1207            Telephony.Threads.CONTENT_URI.buildUpon().
1208                    appendQueryParameter("simple", "true").build();     ----- 这是 URI 的拼接
1209    private static final int RECIPIENT_IDS  = 1;
1210
1211    // Copied from packages/apps/Messaging/src/com/android/messaging/sms/MmsUtils.java.
1212    // NOTE: There are phones on which you can't get the recipients from the thread id for SMS
1213    // until you have a message in the conversation!
1214    private String getRawRecipientIdsForThread(final long threadId) {
1215        if (threadId <= 0) {
1216            return null;
1217        }
1218        final Cursor thread = mContentResolver.query(
1219                ALL_THREADS_URI,
1220                SMS_RECIPIENTS_PROJECTION, "_id=?", new String[]{String.valueOf(threadId)}, null);    --- 这里是根据id查询,如果全查就不要带条件了
1221        if (thread != null) {
1222            try {
1223                if (thread.moveToFirst()) {
1224                    // recipientIds will be a space-separated list of ids into the
1225                    // canonical addresses table.
1226                    return thread.getString(RECIPIENT_IDS);
1227                }
1228            } finally {
1229                thread.close();
1230            }
1231        }
1232        return null;
1233    }
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" );
  1. 更新threads表中的信息

源码位置:packages/providers/TelephonyProvider/src/com/android/providers/telephony/MmsSmsProvider.java

281    static {
282        URI_MATCHER.addURI(AUTHORITY, "conversations", URI_CONVERSATIONS);                   --- 短信界面会话
283        URI_MATCHER.addURI(AUTHORITY, "complete-conversations", URI_COMPLETE_CONVERSATIONS);
284
285        // In these patterns, "#" is the thread ID.
286        URI_MATCHER.addURI(
287                AUTHORITY, "conversations/#", URI_CONVERSATIONS_MESSAGES);
288        URI_MATCHER.addURI(
289                AUTHORITY, "conversations/#/recipients",
290                URI_CONVERSATIONS_RECIPIENTS);
291
292        URI_MATCHER.addURI(
293                AUTHORITY, "conversations/#/subject",
294                URI_CONVERSATIONS_SUBJECT);
295
296        // URI for obtaining all short message count
297        URI_MATCHER.addURI(AUTHORITY, "messagescount", URI_MESSAGES_COUNT);
298
299        // URI for deleting obsolete threads.
300        URI_MATCHER.addURI(AUTHORITY, "conversations/obsolete", URI_OBSOLETE_THREADS);
301
302        URI_MATCHER.addURI(AUTHORITY, "search-message", URI_SEARCH_MESSAGE);
303
304        URI_MATCHER.addURI(
305                AUTHORITY, "messages/byphone/*",
306                URI_MESSAGES_BY_PHONE);
307
308        // In this pattern, two query parameter names are expected:
309        // "subject" and "recipient."  Multiple "recipient" parameters
310        // may be present.
311        URI_MATCHER.addURI(AUTHORITY, "threadID", URI_THREAD_ID);             --根据 thread_id do
312
313        URI_MATCHER.addURI(AUTHORITY, "update-thread/#", URI_UPDATE_THREAD);   --  更新 thread 根据 id
314
315        URI_MATCHER.addURI(AUTHORITY, "update-date", URI_UPDATE_THREAD_DATE);  
316
317        URI_MATCHER.addURI(AUTHORITY, "update-top", URI_UPDATE_THREAD_TOP);
318
319        URI_MATCHER.addURI(
320                AUTHORITY, "conversations/favourite", URI_FAVOURITE_MESSAGES);
321
322        // Use this pattern to query the canonical address by given ID.
323        URI_MATCHER.addURI(AUTHORITY, "canonical-address/#", URI_CANONICAL_ADDRESS);
324
325        // Use this pattern to query all canonical addresses.
326        URI_MATCHER.addURI(AUTHORITY, "canonical-addresses", URI_CANONICAL_ADDRESSES);
327
328        URI_MATCHER.addURI(AUTHORITY, "search", URI_SEARCH);
329        URI_MATCHER.addURI(AUTHORITY, "searchSuggest", URI_SEARCH_SUGGEST);
330
331        // In this pattern, two query parameters may be supplied:
332        // "protocol" and "message." For example:
333        //   content://mms-sms/pending?
334        //       -> Return all pending messages;
335        //   content://mms-sms/pending?protocol=sms
336        //       -> Only return pending SMs;
337        //   content://mms-sms/pending?protocol=mms&message=1
338        //       -> Return the the pending MM which ID equals '1'.
339        //
340        URI_MATCHER.addURI(AUTHORITY, "pending", URI_PENDING_MSG);
341
342        // Use this pattern to get a list of undelivered messages.
343        URI_MATCHER.addURI(AUTHORITY, "undelivered", URI_UNDELIVERED_MSG);
344
345        // Use this pattern to see what delivery status reports (for
346        // both MMS and SMS) have not been delivered to the user.
347        URI_MATCHER.addURI(AUTHORITY, "notifications", URI_NOTIFICATIONS);
348
349        URI_MATCHER.addURI(AUTHORITY, "draft", URI_DRAFT);
350
351        URI_MATCHER.addURI(AUTHORITY, "locked", URI_FIRST_LOCKED_MESSAGE_ALL);
352
353        URI_MATCHER.addURI(AUTHORITY, "locked/#", URI_FIRST_LOCKED_MESSAGE_BY_THREAD_ID);
354
355        URI_MATCHER.addURI(AUTHORITY, "messageIdToThread", URI_MESSAGE_ID_TO_THREAD);
356        //+ req 153968, query the locked messages and draft messages, add by sunhengzhi.wt, 2016-03-30
357        URI_MATCHER.addURI(AUTHORITY, "message/locked", URI_MESSAGE_LOCKED);
358        URI_MATCHER.addURI(AUTHORITY, "message/draft", URI_MESSAGE_DRAFT);
359        //- req 153968, query the locked messages and draft messages, add by sunhengzhi.wt, 2016-03-30
360
361        // bug 154682, group send function, add by sunhengzhi.wt, 2016-04-22
362        URI_MATCHER.addURI(
363                        AUTHORITY, "conversations/#/mult", URI_CONVERSATIONS_MULT_MESSAGES);
364
365        // bug154806, sunhengzhi.wt, 2016-04-30, add, get the database's size
366        URI_MATCHER.addURI(AUTHORITY, "mmssmssize", URI_MMSSMS_SIZE);
367
368        // bug168427, sunhengzhi.wt, 2016-05-25, add, add for the quick search box
369        URI_MATCHER.addURI(AUTHORITY, "search-address-word", URI_SEARCH_ADDRESS);
370        initializeColumnSets();
371    }


 @Override
1658    public int update(Uri uri, ContentValues values,
....
....

1718            case URI_UPDATE_THREAD:                                       ---- 然后从代码就看出来了,就是这里根据id更新
1719                long threadId;
1720                try {
1721                    threadId = Long.parseLong(uri.getLastPathSegment());
1722                } catch (NumberFormatException e) {
1723                    Log.e(LOG_TAG, "Thread ID must be a long.");
1724                    break;
1725                }
1726                updateConversationUnread(db, threadId);
1727                MmsSmsDatabaseHelper.updateThread(db, threadId);
1728                break;
1729
1730            case URI_UPDATE_THREAD_DATE:
1731                MmsSmsDatabaseHelper.updateThreadsDate(db, selection, selectionArgs);
1732                break;
1733            case URI_UPDATE_THREAD_TOP:
1734                 //bug 255905,modify,add,2017-05-09,start
1735                //if (mUseRcsColumns) {
1736                    db.update("threads", values, selection, selectionArgs);
1737                //} else {
1738                 //   throw new IllegalStateException("Only Rcs has this URI:" + uri);
1739                //}
1740                //bug 255905,modify,add,2017-05-09,end
1741                break;
1742            default:
1743                throw new UnsupportedOperationException(
1744                        NO_DELETES_INSERTS_OR_UPDATES + uri);
1745        }

然后其实是有2种方式更新的,

1.  强制更新 thread表
    static void updateConversationDate(Context context) {
        //Work around: com/android/providers/telephony/SmsProvider.java
        Uri uri = ContentUris.withAppendedId(Telephony.Sms.Conversations.CONTENT_URI, -1);
        int ret = context.getContentResolver().delete(uri, null, null);
    }

2.  遍历 thread表,再根据 thread _id 更新

        Cursor cursor = null ;
        Cursor cursorSms = null ;
        try {
            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,Threads.TYPE
            };
            cursor = mContext.getContentResolver().query( sAllThreadsUri, ALL_THREADS_PROJECTION , null ,null, "date DESC" );
            Log.d(TAG, "===cursor=="+  cursor.getCount());
            while(cursor!= null && cursor.moveToNext()){
                int id = cursor.getInt(cursor.getColumnIndex(Threads._ID));
                Log.d(TAG, "===id==="+ id);

        /**
                final String smsSelection = " thread_id =  " + id ;
                String[] aa = { Sms.BODY, Sms.DATE,   Sms.TYPE,Sms.READ };
                cursorSms = mContext.getContentResolver().query(BACKUPSMS_URI, aa, smsSelection, null, Mms.DATE + " DESC");
                if(cursorSms != null && cursorSms.moveToFirst() ){
                    String spin = cursorSms.getString(0);
                    long date = cursorSms.getLong(1);
                    int type = cursorSms.getInt(2);
                    int read = cursorSms.getInt(3);
                    Log.d(TAG, "==spin:"+ spin + ",date:"+ date);
                    ContentValues cc = new ContentValues();
                    cc.put(Threads.DATE, date);
                    cc.put(Threads.SNIPPET_CHARSET, spin);
                    //cc.put(Threads.TYPE, type);
                    //cc.put(Threads.READ, read);

                }
        **/

        //Telephony.Sms.Conversations
        Uri uri = ContentUris.withAppendedId(Uri.parse("content://mms-sms/update-thread"), id);
        //mContext.getContentResolver().update(Threads.CONTENT_URI,   cc,  "_id =  "+ id,  null);
        mContext.getContentResolver().update(uri, cc,  null,  null);
            }
        } catch (Exception e) {
          Log.d(TAG, "update======="+ e.toString());
        }finally{
      cursor! = null
          ...
      ...

    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

空白的泡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值