1. 注册ContentObserver时Sms.Inbox.CONTENT_URI应改成Sms.CONTENT_URI.

getContentResolver().registerContentObserver(Sms.Inbox.CONTENT_URI,
        true, mInboxObserver);

此时Uri是Sms.Inbox.CONTENT_URI,它并没有表示一张表。我将它理解为Sms.CONTENT_URI的一个视图。

getContentResolver().registerContentObserver(Sms.CONTENT_URI,
        true, mInboxObserver);

2. 在使用getContentResolver().update()方法时必须设置selection参数。

如果selection为null,表示Uri表示的所有数据都在update的范围之中。

如果Uri表示某一张表,比如Sms.CONTENT_URI表示Sms表,如果没有设定selection,那么将修改Sms表中所有数据,造成低级但严重错误。

private ContentObserver mInboxObserver = new ContentObserver(null) {
    public void onChange(boolean selfChange) {
        Cursor cursor = getContentResolver().query(Sms.Inbox.CONTENT_URI,
                new String[]{Sms._ID, Sms.THREAD_ID, Sms.TYPE, Sms.BODY, Sms.DATE, Sms.READ},
                "type = " + Sms.MESSAGE_TYPE_INBOX + " and read = 0 and thread_id = " + getOrCreateThreadId(),
                null, null);
        TxrjMessage msg = null;
        if(cursor != null) {
            if(cursor.moveToFirst()) {
                msg = new TxrjMessage();
                msg.setMessageId(cursor.getInt(cursor.getColumnIndex(Sms._ID)));
                msg.setThreadId(cursor.getInt(cursor.getColumnIndex(Sms.THREAD_ID)));
                msg.setType(cursor.getInt(cursor.getColumnIndex(Sms.TYPE)));
                msg.setBody(cursor.getString(cursor.getColumnIndex(Sms.BODY)));
                msg.setTime(cursor.getLong(cursor.getColumnIndex(Sms.DATE)));
                mMessages.add(msg);
                mHandler.sendMessage(mHandler.obtainMessage()); // 在优化过程中会改掉。
            }
            cursor.close();
        }
        if(msg != null) {
            ContentValues values = new ContentValues();
            values.put(Sms._ID, msg.getMessageId()); // Bug语句。
            values.put(Sms.READ, 1);
            getContentResolver().update(Sms.Inbox.CONTENT_URI, values, null, null); // selection为null是个bug。
        }
    }
};

3. 在onChange()方法中使用Handler,使程序在主线程中更新UI,

onChange()方法是否在主线程中执行,有待确定。

private Handler mHandler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        mListAdapter.notifyDataSetChanged();
        mListView.setSelection(mListView.getBottom());
    }
};

4. 在会话列表界面中,点击某个会话打开信息列表界面之前将此会话中的未读信息改为已读。

在ConversationListActivity中点击某个item时首先执行

if(thread.getUnReadCount()>0) {
    ContentValues values = new ContentValues();
    values.put(Sms.READ, 1);
    getContentResolver().update(Sms.Inbox.CONTENT_URI, values,
            "read=0 and thread_id=" + thread.getThreadId(), null);
}

5. 将收到的未读信息在ListView中显示出来,并且修改它的read字段。

在执行getContentResolver.update()之前关闭cursor,否则:

当update()方法执行之后修改了数据,然后再从之前query返回的cursor中获得数据将出现不同步结果。

private ContentObserver mInboxObserver = new ContentObserver(null) {
    public void onChange(boolean selfChange) {
        Log.i("txrjsms", "receive a message.");           
        Cursor cursor = getContentResolver().query(Sms.CONTENT_URI,
                new String[]{Sms._ID, Sms.THREAD_ID, Sms.TYPE, Sms.BODY, Sms.DATE, Sms.READ},
                "type = " + Sms.MESSAGE_TYPE_INBOX + " and read = 0 and thread_id = " + mThreadId,
                null, null);
        TxrjMessage msg = null;
        if(cursor != null) {
            if (cursor.moveToFirst()) {
                msg = new TxrjMessage();
                msg.setMessageId(cursor.getInt(cursor.getColumnIndex(Sms._ID)));
                msg.setThreadId(cursor.getInt(cursor.getColumnIndex(Sms.THREAD_ID)));
                msg.setType(cursor.getInt(cursor.getColumnIndex(Sms.TYPE)));
                msg.setBody(cursor.getString(cursor.getColumnIndex(Sms.BODY)));
                msg.setTime(cursor.getLong(cursor.getColumnIndex(Sms.DATE)));
                cursor.close();
                ContentValues values = new ContentValues();
                values.put(Sms.READ, 1);
                getContentResolver().update(Sms.CONTENT_URI, values, "_id=" + msg.getMessageId(), null);
                mMessages.add(msg);
                mHandler.sendMessage(mHandler.obtainMessage());
            }
        }
    }
};

6. 在uri中指定了具体哪条数据,因此可以将selection置为空。

private void updateMsgType(Uri uri, int type) {
    ContentValues values = new ContentValues();
    values.put(Sms.TYPE, type);
    getContentResolver().update(uri, values, null, null);
}

信息列表中的ContentObserver、CONTENT_URI等的更多相关文章

  1. freecms怎样在信息列表类标签中提取info.content

    原文地址:http://javaz.cn/site/javaz/site_study/info/2015/22026.html 项目地址:http://www.freeteam.cn/ 因为info. ...

  2. 如若已在管理后台更新域名配置,请刷新项目配置后重新编译项目,操作路径:“项目-域名信息” http://www.mysite.com 不在以下 request 合法域名列表中

    报错如图 报错文字如下: 如若已在管理后台更新域名配置,请刷新项目配置后重新编译项目,操作路径:“项目-域名信息” http://www.mysite.net 不在以下 request 合法域名列表中 ...

  3. 【Azure Developer】在Azure Resource Graph Explorer中查看当前订阅下的所有资源信息列表并导出(如VM的名称,IP地址内网/公网,OS,区域等)

    问题描述 通过Azure的Resource Graph Explorer(https://portal.azure.cn/#blade/HubsExtension/ArgQueryBlade),可以查 ...

  4. chmod a+w . 权限控制 su、sudo 修改文件所有者和文件所在组 添加用户到sudoer列表中 当前用户信息

    对当前目录对所有用户开放读写权限 chmod a+r . $ sudo chmod -R a+w /usr/lib/python2.7 所有用户添加文件的写权限 [linux]su.sudo.sudo ...

  5. vs2015 编译时错误列表中没有错误,dll却没有生成出来

    最近发现vs2015的一个问题, 编译时,错误列表中没有错误,dll却没有生成出来,vs重启也无效 解决: 多次排查发现如果一个类库设置的是framework 4.0版本,但引用了framework4 ...

  6. 微信小程序 不在以下合法域名列表中,请参考文档:https://mp.weixin.qq.com/debug/wxadoc/dev/api/network-request.html

    微信小程序  不在以下合法域名列表中,请参考文档:https://mp.weixin.qq.com/debug/wxadoc/dev/api/network-request.html 友情提示: 大家 ...

  7. 从下拉菜单拖拽一个元素 出来,插入到页面中的app 列表中

    1,实现功能:从下拉菜单拖拽一个元素 出来,插入到页面中的app 列表中 并实现app向后移动一个元素的位置: 2.实现思路: 01.遍历下拉菜单,添加拖拽方法,实现位置移动功能: 02.遍历app列 ...

  8. 在GridView列表中使用图片显示记录是否包含附件

    在我的前面很多文章中,都介绍过通用附件模块的管理,本篇随笔主要介绍在一些应用模块中的列表展示中,包含附件的记录,在GridView列表界面中使用图标来快速显示是否有附件的情况. 1.通用附件模块的应用 ...

  9. 在滚动列表中实现视频的播放(ListView & RecyclerView)

    英文原文:Implementing video playback in a scrolled list (ListView & RecyclerView) 本文将讲解如何在列表中实现视频播放. ...

随机推荐

  1. 深度学习Github排名,很不错的介绍

    今天看到这篇文章,把深度学习github排名靠前的项目,介绍了一下,很不错: https://blog.csdn.net/yH0VLDe8VG8ep9VGe/article/details/81611 ...

  2. go语言之进阶篇文件常用操作接口介绍和使用

    一.文件常用操作接口介绍 1.创建文件 法1: 推荐用法 func Create(name string) (file *File, err Error) 根据提供的文件名创建新的文件,返回一个文件对 ...

  3. knockout 多值绑定

    knockout 这种东西现在已经很流行了,相信很多人对它的使用都已经很熟悉了,最近项目开发中发现knockout 绑定用的有些不怎么充分,发现整个page的code 有点累赘. 1.在绑定click ...

  4. [leetcode]Scramble String @ Python

    原题地址:https://oj.leetcode.com/problems/scramble-string/ 题意: Given a string s1, we may represent it as ...

  5. Max Points on a Line leetcode java

    题目: Given n points on a 2D plane, find the maximum number of points that lie on the same straight li ...

  6. Android教材 | 第三章 Android界面事件处理(一)—— 杰瑞教育原创教材试读

      前  言 JRedu Android应用开发中,除了界面编程外,另一个重要的内容就是组件的事件处理.在Android系统中,存在多种界面事件,比如触摸事件.按键事件.点击事件等.在用户交互过程中, ...

  7. pThreads线程(二) 线程同步--互斥量/锁

    互斥量(Mutex)是“mutual exclusion”的缩写.互斥量是实现线程同步,和保护同时写共享数据的主要方法. 互斥量对共享数据的保护就像一把锁.在Pthreads中,任何时候仅有一个线程可 ...

  8. 大数据开发实战:Storm流计算开发

    Storm是一个分布式.高容错.高可靠性的实时计算系统,它对于实时计算的意义相当于Hadoop对于批处理的意义.Hadoop提供了Map和Reduce原语.同样,Storm也对数据的实时处理提供了简单 ...

  9. Java面试问题总结

    前几天Java面试中遇到的问题,这仅仅是当中的一部分问题.面试中有非常多问题是关于数据结构和算法的.在这里做下总结,希望有能力的人能够试着做一下,并在评论区留下您的答案.让大家相互学习.谢谢 程序设计 ...

  10. Android -- 状态栏高度

    干货 Class<?> c = null; Object obj = null; Field field = null; int x = 0, sbar = 0; try { c = Cl ...