分析原因:收到短信,sms表插入信息,触发器会自动更新thread表,更新失败导致一直有一条未读信息数量显示,但在会话列表中却看不到。
      (偶现,低概率。 解决方法:接收新信息插入后,立即查询thread表,如果刚刚的信息查不到,则再次手动更新)

    android\packages\providers\TelephonyProvider\src\com\android\providers\telephony\MmsSmsDatabaseHelper.java中定义了触发器

  1. private void createCommonTriggers(SQLiteDatabase db) {
  2. // Updates threads table whenever a message is added to sms.
  3. db.execSQL("CREATE TRIGGER sms_update_thread_on_insert AFTER INSERT ON sms " +
  4. SMS_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE);
  5.  
  6. // Updates threads table whenever a message in sms is updated.
  7. db.execSQL("CREATE TRIGGER sms_update_thread_date_subject_on_update AFTER" +
  8. " UPDATE OF " + Sms.DATE + ", " + Sms.BODY + ", " + Sms.TYPE +
  9. " ON sms " +
  10. SMS_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE);
  11.  
  12. // Updates threads table whenever a message in sms is updated.
  13. db.execSQL("CREATE TRIGGER sms_update_thread_read_on_update AFTER" +
  14. " UPDATE OF " + Sms.READ +
  15. " ON sms " +
  16. "BEGIN " +
  17. SMS_UPDATE_THREAD_READ_BODY +
  18. "END;");
  19.  
  20. // TODO Add triggers for SMS retry-status management.
  21.  
  22. // Update the error flag of threads when the error type of
  23. // a pending MM is updated.
  24. db.execSQL("CREATE TRIGGER update_threads_error_on_update_mms " +
  25. " AFTER UPDATE OF err_type ON pending_msgs " +
  26. " WHEN (OLD.err_type < 10 AND NEW.err_type >= 10)" +
  27. " OR (OLD.err_type >= 10 AND NEW.err_type < 10) " +
  28. "BEGIN" +
  29. " UPDATE threads SET error = " +
  30. " CASE" +
  31. " WHEN NEW.err_type >= 10 THEN error + 1" +
  32. " ELSE error - 1" +
  33. " END " +
  34. " WHERE _id =" +
  35. " (SELECT DISTINCT thread_id" +
  36. " FROM pdu" +
  37. " WHERE _id = NEW.msg_id); " +
  38. "END;");
  39.  
  40. // Update the error flag of threads after a text message was
  41. // failed to send/receive.
  42. db.execSQL("CREATE TRIGGER update_threads_error_on_update_sms " +
  43. " AFTER UPDATE OF type ON sms" +
  44. " WHEN (OLD.type != 5 AND NEW.type = 5)" +
  45. " OR (OLD.type = 5 AND NEW.type != 5) " +
  46. "BEGIN " +
  47. " UPDATE threads SET error = " +
  48. " CASE" +
  49. " WHEN NEW.type = 5 THEN error + 1" +
  50. " ELSE error - 1" +
  51. " END " +
  52. " WHERE _id = NEW.thread_id; " +
  53. "END;");
  54. }

  Ril层接收新信息会通过Framework发通知——android.provider.Telephony.SMS_DELIVER

   APP层MMS开始处理com.android.mms.transaction.PrivilegedSmsReceiver接收广播,  

  1. com.android.mms.transaction.SmsReceiverService调用handleSmsReceived(intent, error)方法,
    ————>saveMessageToPhone(msgs, error, format)————> insertMessage(this, msgs, error, format)
    ————>storeMessage(context, msgs, error);
  1. storeMessage(context, msgs, error)方法最后,增加查询thread表,确认信息更新是否成功,如果thread表信息更新失败,手动更新.
  1. private Uri storeMessage(Context context, SmsMessage[] msgs, int error) {
  2. // Check to see whether short message count is up to 2000 for cmcc
  3. if (MessageUtils.checkIsPhoneMessageFull(this)) {
  4. return null;
  5. }
  6.  
  7. SmsMessage sms = msgs[0];
  8.  
  9. // Store the message in the content provider.
  10. ContentValues values = extractContentValues(sms);
  11. values.put(Sms.ERROR_CODE, error);
  12. values.put(Sms.PHONE_ID, SubscriptionManager.getPhoneId(sms.getSubId()));
  13.  
  14. int pduCount = msgs.length;
  15.  
  16. if (pduCount == 1) {
  17. // There is only one part, so grab the body directly.
  18. values.put(Inbox.BODY, replaceFormFeeds(sms.getDisplayMessageBody()));
  19. } else {
  20. // Build up the body from the parts.
  21. StringBuilder body = new StringBuilder();
  22. for (int i = 0; i < pduCount; i++) {
  23. sms = msgs[i];
  24. if (sms.mWrappedSmsMessage != null) {
  25. body.append(sms.getDisplayMessageBody());
  26. }
  27. }
  28. values.put(Inbox.BODY, replaceFormFeeds(body.toString()));
  29. }
  30.  
  31. // Make sure we've got a thread id so after the insert we'll be able to delete
  32. // excess messages.
  33. Long threadId = values.getAsLong(Sms.THREAD_ID);
  34. String address = values.getAsString(Sms.ADDRESS);
  35.  
  36. // Code for debugging and easy injection of short codes, non email addresses, etc.
  37. // See Contact.isAlphaNumber() for further comments and results.
  38. // switch (count++ % 8) {
  39. // case 0: address = "AB12"; break;
  40. // case 1: address = "12"; break;
  41. // case 2: address = "Jello123"; break;
  42. // case 3: address = "T-Mobile"; break;
  43. // case 4: address = "Mobile1"; break;
  44. // case 5: address = "Dogs77"; break;
  45. // case 6: address = "****1"; break;
  46. // case 7: address = "#4#5#6#"; break;
  47. // }
  48.  
  49. if (!TextUtils.isEmpty(address)) {
  50. Contact cacheContact = Contact.get(address,true);
  51. if (cacheContact != null) {
  52. address = cacheContact.getNumber();
  53. }
  54. } else if (TextUtils.isEmpty(address)
  55. && getResources().getBoolean(R.bool.def_hide_unknown_sender)) {
  56. values.put(Sms.ADDRESS, "");
  57. } else {
  58. address = getString(R.string.unknown_sender);
  59. values.put(Sms.ADDRESS, address);
  60. }
  61.  
  62. if (((threadId == null) || (threadId == 0)) && (address != null)) {
  63. threadId = Conversation.getOrCreateThreadId(context, address);
  64. values.put(Sms.THREAD_ID, threadId);
  65. }
  66.  
  67. ContentResolver resolver = context.getContentResolver();
  68.  
  69. Uri insertedUri = SqliteWrapper.insert(context, resolver, Inbox.CONTENT_URI, values);
  70.  
  71. // Now make sure we're not over the limit in stored messages
  72. Recycler.getSmsRecycler().deleteOldMessagesByThreadId(context, threadId);
  73. MmsWidgetProvider.notifyDatasetChanged(context);
  74.  
  75. //---add by antoon ----------------------------------------------------------------------------------------------------
  76. //query thread to check if thread update or create successfully, if not update here
  77. StringBuilder sbUri = new StringBuilder(3);
  78. sbUri.append("content://mms-sms/conversations/").append(threadId).append("/recipients");
  79. Cursor curosr = resolver.query(Uri.parse(sbUri.toString()),null,null,null,null);
  80. Log.i("antoon", "SmsReceiverService, --> storeMessage , curosr = "+curosr);
  81. if(curosr == null || curosr.getCount()==0){
  82. SqliteWrapper.insert(context, resolver, Telephony.Threads.CONTENT_URI, values);//------手动更新thread表
  83. }else{
  84. Log.d("antoon", "SmsReceiverService, --> storeMessage , curosr.getCount = " + curosr.getCount());
  85. }
    //---end add by antoon -------------------------------------------------------------------------------------------------
  86.  
  87. return insertedUri;
  88. }

TelephonyProvider中增加相应的数据库处理。 android\packages\providers\TelephonyProvider\src\com\android\providers\telephony\MmsSmsProvider.java中增加 insert/update 处理

  1. @Override
  2. public Uri insert(Uri uri, ContentValues values) {
  3. if (URI_MATCHER.match(uri) == URI_PENDING_MSG) {
  4. SQLiteDatabase db = mOpenHelper.getWritableDatabase();
  5. long rowId = db.insert(TABLE_PENDING_MSG, null, values);
  6. return Uri.parse(uri + "/" + rowId);
  7. }
  8. //------ add by antoon
  9. else if(URI_MATCHER.match(uri) == URI_CONVERSATIONS){
  10. Log.i("antoon", "MmsSmsProvider -> insert, URI_CONVERSATIONS");
  11. insertThreadsIfDataLost(values);
  12. return null;
  13. }
  14.  
  15. //------ end add by antoon
  16. throw new UnsupportedOperationException(NO_DELETES_INSERTS_OR_UPDATES + uri);
  17. }
  1. //------add by antoon, create thread data if thread trigger fail
  2. public void insertThreadsIfDataLost(ContentValues values) {
  3. long _id = values.getAsLong(Sms.THREAD_ID);
  4. long date = values.getAsLong(Sms.DATE);
  5. String snippet = values.getAsString(Sms.BODY);
  6. String address = values.getAsString(Sms.ADDRESS);
  7.  
  8. //create a new thread id with new msg address, then update threadId to _id
  9. List<String> list = new ArrayList<String>();
  10. list.add(address);
  11. Cursor cursor = getThreadId(list, false);//------这里的查询会判断threadId是否存在,如果不存在则创建threadId新数据,如果存在则直接返回
  12. cursor.moveToFirst();
  13. long threadId = cursor.getLong(0);
  14. cursor.close();
  15. /*
  16. String updateSql = "UPDATE threads SET date = ?, snippet = ?, snippet_cs = 0, read=0, "
  17. + "message_count = (SELECT COUNT(sms._id) FROM sms WHERE sms.thread_id = ? AND sms.type!= 3) + "
  18. +"(SELECT COUNT(pdu._id) FROM pdu WHERE pdu.thread_id = ? AND (m_type=132 OR m_type=130 OR m_type=128) AND msg_box!= 3)"
  19. + " WHERE threads._id = ?";
  20. */
  21.  
  22. StringBuilder sqlSb = new StringBuilder(14);
  23. sqlSb.append("UPDATE threads SET _id =").append(_id)
  24. .append(", date =").append(date)
  25. .append(", snippet ='").append(snippet)
  26. .append("', snippet_cs = 0, read=0, ")
  27. .append("message_count = (SELECT COUNT(sms._id) FROM sms WHERE sms.thread_id = ").append(threadId)
  28. .append(" AND sms.type!= 3) + (SELECT COUNT(pdu._id) FROM pdu WHERE pdu.thread_id =").append(threadId)
  29. .append(" AND (m_type=132 OR m_type=130 OR m_type=128) AND msg_box!= 3) WHERE threads._id = ").append(threadId)
  30. ;
  31.  
  32. SQLiteDatabase db = mOpenHelper.getReadableDatabase();
  33. db.execSQL(sqlSb.toString());
  34.  
  35. Log.i("antoon", "sqlSb = " + sqlSb);
  36. }
  37. //------end add by antoon
  1.  

接收新信息,在会话中看不到(thread表数据插入/更新失败)的更多相关文章

  1. android6.0锁屏界面接收新通知处理流程

    灭屏状态下,接收新信息,屏幕会半亮显示通知流程: 1,应用构造notification后,传给NotificationManager,而后进入NotificationManagerService处理. ...

  2. ABAP 动态备份自建表数据到新表(自建表有数据的情况下要改字段长度或者其他)

    当abaper开发好一个程序给用户使用一段时间后,发现某个字段的长度需要修改,但数据库表中已经存在很多数据,冒然直接改表字段可能会导致数据丢失,这种问题的后果可能非常严重. 所以我想到先复制出一个新表 ...

  3. MQTT的学习研究(四)moquette-mqtt 的使用之mqtt Blocking API客户端订阅并接收主题信息

    在上面两篇关于mqtt的broker的启动和mqtt的服务端发布主题信息之后,我们客户端需要订阅相关的信息并接收相关的主题信息. package com.etrip.mqtt; import java ...

  4. 记一次PHP实现接收邮件信息(我这里测试的腾讯企业邮件)

    PHP实现接收邮件信息(我这里测试的腾讯企业邮件) , 其他的类型的没有测,应该只要更换pop3地址 端口号就可以. 代码如下(代码参考网络分享): <?php //此处查看链接状态 heade ...

  5. 【多端应用开发系列1.1.1 —— Android:使用新浪API V2】服务器Json数据处理——Json数据概述

    [前白] 一些基础的东西本系列中就不再详述了,争取尽量写些必不可少的技术要点. 由于本系列把Web Service 构建放到了第二部分,Android项目就采用新浪微博API v2作为服务器端. [原 ...

  6. MySQL触发器初试:当A表插入新记录,自动在B表中插入相同ID的记录

    今天第一次用MySQL的触发器,怕忘了,赶紧写篇博客记录一下. 废话不说,先上语法: 1 CREATE TRIGGER trigger_name 2 { BEFORE | AFTER } { INSE ...

  7. SQL语句 在一个表中插入新字段

    SQL语句 在一个表中插入新字段: alter table 表名 add 字段名 字段类型 例: alter table OpenCourses add Audio varchar(50)alter ...

  8. mysql复制表数据或表结构到新表中

    MySQL复制表数据到新表的几个步骤. 1.MySQL复制表结构及数据到新表 CREATE TABLE new_table SELECT * FROM old_table; 2.只复制表结构到新表 C ...

  9. 会话的保持和form表单

    会话的保持和form表单 cookie 设置cookie from django.shortcuts import render, HttpResponse, redirect, reverse de ...

随机推荐

  1. 41、javaMail机制

    SMTP 是一种TCP协议支持的提供可靠且有效电子邮件传输的应用层协议.SMTP 是建立在 TCP上的一种邮件服务,主要用于传输系统之间的邮件信息并提供来信有关的通知. package com.ith ...

  2. MATLAB 文件对话框之图片格式转换

    localpathname为当前路径,需要保存图片的位置,根据自己的实际路径设置,usedpathname用来保存打开的文件位置,方便下次打开文件对话框以上次的路径为默认路径. global used ...

  3. 博客CSS

    <p style="background: #CFE0F8; padding: 5px;">理解Code First及其约定和配置</p> <p id ...

  4. 微信支付之JSAPI开发第一篇-基本概念

    申请权限 具体步骤就不说了,进入微信支付商户平台进行申请认证,认证成功后在微信公众号后台会有个微信支付的菜单按钮,点击后会有如下的信息 配置 在进行微信支付开发之前,必须进行一些必要的配置,如果这些配 ...

  5. XidianOJ 1041: Franky的游戏O

    题目描述 Franky是super的人造人,来到了n*m的棋盘世界玩冒险游戏. n×m的棋盘由n行每行m个方格组成,左上角的方格坐标是(0,0),右下角的方格坐标是(n-1,m-1). 每次游戏时,他 ...

  6. 如何正确建立MYSQL数据库索引

    索引是快速搜索的关键.MySQL索引的建立对于MySQL的高效运行是很重要的.下面介绍几种常见的MySQL索引类型. 在数据库表中,对字段建立索引可以大大提高查询速度.假如我们创建了一个 mytabl ...

  7. linux学习 联网

    /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0ONBOOT=yesBOOTPROTO=staticIPADDR=192.168.199.** ...

  8. XtraBackup安装

    1.从官网下载XtraBackup2.4.4. percona-xtrabackup-24-2.4.4-1.el6.x86_64.rpm 2.安装依赖包 yum -y install perl per ...

  9. sql group by datetime on day

    SELECT        DATEADD(dd, DATEDIFF(dd, 0, postDate), 0)FROM          tableWHERE        (postDate > ...

  10. centos rar安装

    wget http://www.rarsoft.com/rar/rarlinux-x64-5.1.1.tar.gz tar -zxvf rarlinux-x64-5.1.1.tar.gz # cd r ...