zoukankan      html  css  js  c++  java
  • 接收新信息,在会话中看不到(thread表数据插入/更新失败)

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

        androidpackagesprovidersTelephonyProvidersrccomandroidproviders elephonyMmsSmsDatabaseHelper.java中定义了触发器

    private void createCommonTriggers(SQLiteDatabase db) {
            // Updates threads table whenever a message is added to sms.
            db.execSQL("CREATE TRIGGER sms_update_thread_on_insert AFTER INSERT ON sms " +
                       SMS_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE);
    
            // Updates threads table whenever a message in sms is updated.
            db.execSQL("CREATE TRIGGER sms_update_thread_date_subject_on_update AFTER" +
                       "  UPDATE OF " + Sms.DATE + ", " + Sms.BODY + ", " + Sms.TYPE +
                       "  ON sms " +
                       SMS_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE);
    
            // Updates threads table whenever a message in sms is updated.
            db.execSQL("CREATE TRIGGER sms_update_thread_read_on_update AFTER" +
                       "  UPDATE OF " + Sms.READ +
                       "  ON sms " +
                       "BEGIN " +
                       SMS_UPDATE_THREAD_READ_BODY +
                       "END;");
    
    
            // TODO Add triggers for SMS retry-status management.
    
            // Update the error flag of threads when the error type of
            // a pending MM is updated.
            db.execSQL("CREATE TRIGGER update_threads_error_on_update_mms " +
                       "  AFTER UPDATE OF err_type ON pending_msgs " +
                       "  WHEN (OLD.err_type < 10 AND NEW.err_type >= 10)" +
                       "    OR (OLD.err_type >= 10 AND NEW.err_type < 10) " +
                       "BEGIN" +
                       "  UPDATE threads SET error = " +
                       "    CASE" +
                       "      WHEN NEW.err_type >= 10 THEN error + 1" +
                       "      ELSE error - 1" +
                       "    END " +
                       "  WHERE _id =" +
                       "   (SELECT DISTINCT thread_id" +
                       "    FROM pdu" +
                       "    WHERE _id = NEW.msg_id); " +
                       "END;");
    
            // Update the error flag of threads after a text message was
            // failed to send/receive.
            db.execSQL("CREATE TRIGGER update_threads_error_on_update_sms " +
                       "  AFTER UPDATE OF type ON sms" +
                       "  WHEN (OLD.type != 5 AND NEW.type = 5)" +
                       "    OR (OLD.type = 5 AND NEW.type != 5) " +
                       "BEGIN " +
                       "  UPDATE threads SET error = " +
                       "    CASE" +
                       "      WHEN NEW.type = 5 THEN error + 1" +
                       "      ELSE error - 1" +
                       "    END " +
                       "  WHERE _id = NEW.thread_id; " +
                       "END;");
        }
    View Code

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

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

    com.android.mms.transaction.SmsReceiverService调用handleSmsReceived(intent, error)方法,
    ————>saveMessageToPhone(msgs, error, format)————> insertMessage(this, msgs, error, format)
    ————>storeMessage(context, msgs, error);

    storeMessage(context, msgs, error)方法最后,增加查询thread表,确认信息更新是否成功,如果thread表信息更新失败,手动更新.
     private Uri storeMessage(Context context, SmsMessage[] msgs, int error) {
            // Check to see whether short message count is up to 2000 for cmcc
            if (MessageUtils.checkIsPhoneMessageFull(this)) {
                return null;
            }
    
            SmsMessage sms = msgs[0];
    
            // Store the message in the content provider.
            ContentValues values = extractContentValues(sms);
            values.put(Sms.ERROR_CODE, error);
            values.put(Sms.PHONE_ID, SubscriptionManager.getPhoneId(sms.getSubId()));
    
            int pduCount = msgs.length;
    
            if (pduCount == 1) {
                // There is only one part, so grab the body directly.
                values.put(Inbox.BODY, replaceFormFeeds(sms.getDisplayMessageBody()));
            } else {
                // Build up the body from the parts.
                StringBuilder body = new StringBuilder();
                for (int i = 0; i < pduCount; i++) {
                    sms = msgs[i];
                    if (sms.mWrappedSmsMessage != null) {
                        body.append(sms.getDisplayMessageBody());
                    }
                }
                values.put(Inbox.BODY, replaceFormFeeds(body.toString()));
            }
    
            // Make sure we've got a thread id so after the insert we'll be able to delete
            // excess messages.
            Long threadId = values.getAsLong(Sms.THREAD_ID);
            String address = values.getAsString(Sms.ADDRESS);
    
            // Code for debugging and easy injection of short codes, non email addresses, etc.
            // See Contact.isAlphaNumber() for further comments and results.
    //        switch (count++ % 8) {
    //            case 0: address = "AB12"; break;
    //            case 1: address = "12"; break;
    //            case 2: address = "Jello123"; break;
    //            case 3: address = "T-Mobile"; break;
    //            case 4: address = "Mobile1"; break;
    //            case 5: address = "Dogs77"; break;
    //            case 6: address = "****1"; break;
    //            case 7: address = "#4#5#6#"; break;
    //        }
    
            if (!TextUtils.isEmpty(address)) {
                Contact cacheContact = Contact.get(address,true);
                if (cacheContact != null) {
                    address = cacheContact.getNumber();
                }
            } else if (TextUtils.isEmpty(address)
                    && getResources().getBoolean(R.bool.def_hide_unknown_sender)) {
                values.put(Sms.ADDRESS, "");
            } else {
                address = getString(R.string.unknown_sender);
                values.put(Sms.ADDRESS, address);
            }
    
            if (((threadId == null) || (threadId == 0)) && (address != null)) {
                threadId = Conversation.getOrCreateThreadId(context, address);
                values.put(Sms.THREAD_ID, threadId);
            }
    
            ContentResolver resolver = context.getContentResolver();
    
            Uri insertedUri = SqliteWrapper.insert(context, resolver, Inbox.CONTENT_URI, values);
    
            // Now make sure we're not over the limit in stored messages
            Recycler.getSmsRecycler().deleteOldMessagesByThreadId(context, threadId);
            MmsWidgetProvider.notifyDatasetChanged(context);
    
     //---add by antoon ----------------------------------------------------------------------------------------------------
            //query thread to check if thread update or create successfully, if not update here
            StringBuilder sbUri = new StringBuilder(3);
            sbUri.append("content://mms-sms/conversations/").append(threadId).append("/recipients");
            Cursor curosr = resolver.query(Uri.parse(sbUri.toString()),null,null,null,null);
            Log.i("antoon", "SmsReceiverService, --> storeMessage , curosr = "+curosr);
            if(curosr == null || curosr.getCount()==0){
                SqliteWrapper.insert(context, resolver, Telephony.Threads.CONTENT_URI, values);//------手动更新thread表
            }else{
                Log.d("antoon", "SmsReceiverService, --> storeMessage , curosr.getCount = " + curosr.getCount());
            }
    //---end add by antoon ------------------------------------------------------------------------------------------------- return insertedUri; }

     TelephonyProvider中增加相应的数据库处理。 androidpackagesprovidersTelephonyProvidersrccomandroidproviders elephonyMmsSmsProvider.java中增加 insert/update 处理

    @Override
        public Uri insert(Uri uri, ContentValues values) {
            if (URI_MATCHER.match(uri) == URI_PENDING_MSG) {
                SQLiteDatabase db = mOpenHelper.getWritableDatabase();
                long rowId = db.insert(TABLE_PENDING_MSG, null, values);
                return Uri.parse(uri + "/" + rowId);
            }
    //------ add by antoon
            else if(URI_MATCHER.match(uri) == URI_CONVERSATIONS){
                Log.i("antoon", "MmsSmsProvider -> insert,  URI_CONVERSATIONS");
                insertThreadsIfDataLost(values);
                return null;
            }

    //------ end add by antoon throw new UnsupportedOperationException(NO_DELETES_INSERTS_OR_UPDATES + uri); }
    //------add by antoon, create thread data if thread trigger fail
        public void insertThreadsIfDataLost(ContentValues values) {
            long _id = values.getAsLong(Sms.THREAD_ID);
            long date = values.getAsLong(Sms.DATE);
            String snippet = values.getAsString(Sms.BODY);
            String address = values.getAsString(Sms.ADDRESS);
    
            //create a new thread id with new msg address, then update threadId to _id
            List<String> list = new ArrayList<String>();
            list.add(address);
            Cursor cursor = getThreadId(list, false);//------这里的查询会判断threadId是否存在,如果不存在则创建threadId新数据,如果存在则直接返回
            cursor.moveToFirst();
            long threadId = cursor.getLong(0);
            cursor.close();
            /*
            String updateSql = "UPDATE threads SET date = ?, snippet = ?, snippet_cs = 0, read=0, "
                    + "message_count = (SELECT COUNT(sms._id) FROM sms WHERE sms.thread_id = ? AND sms.type!= 3) + "
                    +"(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)"
                    + " WHERE threads._id = ?";
            */
    
            StringBuilder sqlSb = new StringBuilder(14);
            sqlSb.append("UPDATE threads SET _id =").append(_id)
                    .append(", date =").append(date)
                    .append(", snippet ='").append(snippet)
                    .append("', snippet_cs = 0, read=0, ")
                    .append("message_count = (SELECT COUNT(sms._id) FROM sms WHERE sms.thread_id = ").append(threadId)
                    .append(" AND sms.type!= 3) + (SELECT COUNT(pdu._id) FROM pdu WHERE pdu.thread_id =").append(threadId)
                    .append(" AND (m_type=132 OR m_type=130 OR m_type=128) AND msg_box!= 3) WHERE threads._id = ").append(threadId)
                    ;
    
    
            SQLiteDatabase db = mOpenHelper.getReadableDatabase();
            db.execSQL(sqlSb.toString());
    
            Log.i("antoon", "sqlSb = " + sqlSb);
        }
    //------end add by antoon


  • 相关阅读:
    指针数组和数组指针
    initializer_list
    main:处理命令行选项
    Synchronized 和Lock区别
    sleep和wait的区别
    什么时候会发生类初始化
    类的加载与ClassLoader的理解
    获取Class类的实例
    元注解
    IO流思维导图
  • 原文地址:https://www.cnblogs.com/antoon/p/Mms.html
Copyright © 2011-2022 走看看