信息会话Thread_id异常处理(MMS草稿修改收件人,SMS新信息丢失thread数据)

1, sms收到信息,thread表没有create新数据。导致一直有一条未读信息数量显示,但在会话列表中却看不到。
(偶现。 解决方法:查询未读信息时,过滤thread丢失的sms信息。先规避此Bug)

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

  com.android.mms.transaction.PrivilegedSmsReceiver接收广播,应用程序MMS开始处理

protected void onReceiveWithPrivilege(Context context, Intent intent, boolean privileged) {
        String action = intent.getAction();
        // If ‘privileged‘ is false, it means that the intent was delivered to the base
        // no-permissions receiver class.  If we get an SMS_RECEIVED message that way, it
        // means someone has tried to spoof the message by delivering it outside the normal
        // permission-checked route, so we just ignore it.
        if (!privileged && (Intents.SMS_DELIVER_ACTION.equals(action) ||
                "android.cellbroadcastreceiver.CB_AREA_INFO_RECEIVED".equals(action))) {
            return;
        }

        intent.setClass(context, SmsReceiverService.class);
        intent.putExtra("result", getResultCode());
        beginStartingService(context, intent);
    }
public static void beginStartingService(Context context, Intent intent) {
        synchronized (mStartingServiceSync) {
            if (mStartingService == null) {
                PowerManager pm =
                    (PowerManager)context.getSystemService(Context.POWER_SERVICE);
                mStartingService = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                        "StartingAlertService");
                mStartingService.setReferenceCounted(false);
            }
            mStartingService.acquire();//使用PowerManager.WakeLock保证Service在灭屏状态下依然可以运行
            context.startService(intent);
        }
    }
SmsReceiverService从Intent中获取sms数据,然后插入数据库  private Uri insertMessage(Context context, SmsMessage[] msgs, int error, String format){...}
调用storeMessage(Context context, SmsMessage[] msgs, int error)时,会对threadId进行判断,新接收信息是不可能有threadId的,所以要创建thread
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 messagesRecycler.getSmsRecycler().deleteOldMessagesByThreadId(context, threadId);MmsWidgetProvider.notifyDatasetChanged(context);

return insertedUri;

从代码看不应该出现Bug反馈的问题。但thread表进行数据更新时出现create thread fail,或者后续更新时,将new-created-thread-data删掉,就会出现此BUG.

客户催促,版本量产在即,只好先规避此问题。在查询数据时过滤sms中存在,但thread中不存在的thread_id.

case URI_UNREAD_AND_LOST_THREADS: { //自定义一个查询类型,对于unread Sms进行thread_id判断过滤
                String unreadSmsQuery = "SELECT _id, thread_id, address "
                        + "FROM sms "
                        + "WHERE sms.read = 0 AND thread_id NOT IN( SELECT _id FROM threads)";

                cursor = mOpenHelper.getReadableDatabase().rawQuery(unreadSmsQuery, EMPTY_STRING_ARRAY);
                if(cursor!=null && cursor.getCount()>0){
                    //should repair the lost data in thread table, but I have no good idea now, so just leave it
                    Log.e("antoon", "MmsSmsProvider, have lost thread sms : "+cursor.getCount());
                }
        return cursor;
}
-------------------------------------------------------- 华丽的分割线 ------------------------------------------------

2, 彩信草稿修改收件人会产生新的thread。
(必现。 解决方法:将原来的Thread_id和新的收件人传递到Provider,对收件人进行更新,避免生成新的Thread)

MMS草稿保存

private void asyncUpdateDraftMmsMessage(final Conversation conv, final boolean isStopping) {
        if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
            LogTag.debug("asyncUpdateDraftMmsMessage conv=%s mMessageUri=%s", conv, mMessageUri);
        }
        final HashMap<Uri, InputStream> preOpenedFiles =
                mSlideshow.openPartFiles(mContentResolver);

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    DraftCache.getInstance().setSavingDraft(true);

                    final PduPersister persister = PduPersister.getPduPersister(mActivity);
                    final SendReq sendReq = makeSendReq(conv, mSubject);
                    persister.setMmsDraftThreadId(mOldMmsDraftThreadId);//add by antoon, send old thread_id to pdu

                    if (mMessageUri == null) {
                        mMessageUri = createDraftMmsMessage(persister, sendReq, mSlideshow, null,
                                mActivity, preOpenedFiles);//对于MMS保存,thread_id会在pdu保存时创建
                    } else {
                        updateDraftMmsMessage(mMessageUri, persister, mSlideshow, sendReq,
                                preOpenedFiles);//修改之前保存的MMS后,pdu更新数据,这里会根据收件人getOrCreateThreadId,所以修改收件人会导致创建新的thread
                    }
                    ensureThreadIdIfNeeded(conv, isStopping);//这里确认thread_id创建或获取成功,否则再次执行getOrCreateThreadId
                    conv.setDraftState(true);
                    if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
                        LogTag.debug("asyncUpdateDraftMmsMessage conv: " + conv +
                                " uri: " + mMessageUri);
                    }

                    // Be paranoid and delete any SMS drafts that might be lying around. Must do
                    // this after ensureThreadId so conv has the correct thread id.
                    asyncDeleteDraftSmsMessage(conv);
                } finally {
                    DraftCache.getInstance().setSavingDraft(false);
                    closePreOpenedFiles(preOpenedFiles);
                }
            }
        }, "WorkingMessage.asyncUpdateDraftMmsMessage").start();
    }

看看  ensureThreadIdIfNeeded(conv, isStopping)

private void ensureThreadIdIfNeeded(final Conversation conv, final boolean isStopping) {
        if (isStopping && conv.getMessageCount() == 0) {
            // We need to save the drafts in an unorphaned thread id. When the user goes
            // back to ConversationList while we‘re saving a draft from CMA‘s.onStop,
            // ConversationList will delete all threads from the thread table that
            // don‘t have associated sms or pdu entries. In case our thread got deleted,
            // well call clearThreadId() so ensureThreadId will query the db for the new
            // thread.
            conv.clearThreadId();   // force us to get the updated thread id
        }
        if (!conv.getRecipients().isEmpty()) {
            conv.ensureThreadId();
        }
    }
public synchronized void clearThreadId() {
        // remove ourself from the cache
        if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
            LogTag.debug("clearThreadId old threadId was: " + mThreadId + " now zero");
        }
        Cache.remove(mThreadId);

        mThreadId = 0;
}

public synchronized long ensureThreadId() {
        if (DEBUG || DELETEDEBUG) {
            LogTag.debug("ensureThreadId before: " + mThreadId);
        }
        if (mThreadId <= 0) {
            if (mIsGroupChat && mGroupChat != null) {
                HashSet<String> numbers = new HashSet<String>();
                numbers.add(String.valueOf(mGroupChat.getThreadId()));
                ContactList groupRecip = ContactList.getByNumbers(numbers, false);
                mThreadId = getOrCreateThreadId(mContext, groupRecip, mIsGroupChat);
            } else {
                mThreadId = getOrCreateThreadId(mContext, mRecipients, mIsGroupChat);
            }
        }
        if (DEBUG || DELETEDEBUG) {
            LogTag.debug("ensureThreadId after: " + mThreadId);
        }

        return mThreadId;
}

对于MMS, SMS草稿保存时都会调用 ensureThreadIdIfNeeded  , 如果修改了收件人,应该都会有thread_id重建,获取操作。

但是对于SMS却没有反馈此问题,是怎么回事呢?

时间: 2024-11-03 03:27:28

信息会话Thread_id异常处理(MMS草稿修改收件人,SMS新信息丢失thread数据)的相关文章

Sql Server之使用T_SQL创建,修改,查看数据库信息

一.使用Transact_SQL创建数据库 Transact_SQL语法如下:  create database database_name   [ on     [primary]  [<filespec> [,...n] ]   ]   [ log on    [<filespec>[,...n]]   ];   <filespec>::=    (      name=logical_file_name      [  ,  newname = new_login

修改Exchange邮件报警信息

修改Exchange邮件报警信息 目前XX集团邮件系统的报警信息如下, 报警主题及默认文本如下图: 解决办法: New-SystemMessage –QuotaMessageType WarningMailbox –Language En –Text "Your mailbox is becoming dangerously full. Please remove some messages or talk to your administrator about having your mail

nginx 安全笔记 (修改nginx的header信息和错误显示版本号)

随笔记载,欢迎指正: 修改nginx的header信息和错误显示版本号 1.隐藏版本号: nginx的配置文件nginx.conf找到http栏目加入: server_tokens off; 2.修改显示nginx的名称 需要修改源码文件: /opt/soft/nginx-1.2.0/src/http/ngx_http_special_response.c vi /opt/soft/nginx-1.2.0/src/http/ngx_http_special_response.c 找到29行: 2

项目SVN的IP地址发生变化时修改SVN为新的IP地址

在eclipse或者Myeclipse自带的svn:subclipse中修改ip地址 项目开发中有可能要修改SVN的IP地址,entries文件里面包含svn服务器的地址信息.每个文件夹都会产生一个entries文件信息.在myeclipse或者flash builder中    可以借助可视化界面来修改IP地址.步骤如下: 1.点击Window--->Others Views 选择SVN Repositores资源库视图. 2.选中要修改的svn地址,右键点击properties属性,在弹出的

UWP 应用获取各类系统、用户信息 (1) - 设备和系统的基本信息、应用包信息、用户数据账户信息和用户账户信息

应用开发中,开发者时常需要获取一些系统.用户信息用于数据统计遥测.问题反馈.用户识别等功能.本文旨在介绍在 Windows UWP 应用中获取一些常用系统.用户信息的方法.示例项目代码可参见 Github: https://github.com/validvoid/UWP-SystemInfoCollector 由于涉及内容较多,故本文会分为多篇展开.本篇介绍获取设备和系统的基本信息.应用包信息.用户数据账户信息和用户账户信息. 原博客阅读地址:http://validvoid.net/uwp-

powerDesigner将name信息生成到备注中,导出语句有备注信息

name注释信息 在创建pdm时由于需要在name列填写的是以后要在表中创建的注释信息,comment中则写的说明信息字数比较多.默认情况下在生成建表sql时不能将name生成注释信息,进行如下设置可以讲name生成注释信息. www.twitterchina.com1)选择database->edit current dbms-->Column-->ColumnComment将comment on column [%QUALIFIER%]%TABLE%.%COLUMN% is%.q:C

从返回的HTTP Header信息中隐藏Apache的版本号及PHP的X-Powered-By信息

默认情况下,很多apache安装时会显示版本号及操作系统版本,甚至会显示服务器上安装的是什么样的apache模块.这些信息可以为黑客所用,并且黑客还可以从中得知你所配置的服务器上的很多设置都是默认状态. 这里有两条语句,你需要添加到你的httpd.conf文件中:ServerSignature OffServerTokens Prod ServerSignature该参数设置 出现在apache所产生的像404页面.目录列表等页面的底部,三个选项 On|Off|EMai 主要起开关作用,推荐设置

windows系统自带命令查看硬件信息,怎样dos命令查看硬盘和内存/CPU信息

如何在windows系统自带命令查看硬件信息,怎样dos命令查看硬盘和内存/CPU信息?最直接的是:开始→运行→CMD打开命令提示符,在该窗口下输入systeminfo执行,即可看到几乎所有想知道的系统信息,甚至包括机器上已安装的网卡及其IP. 问题描述: 如何从系统中 查看主板上内存条的数量. 最佳答案: 在cmd命令下 输入:wmic memorychip list brief 就会看到内存条的数量 如何在windows系统自带命令查看硬件信息? 对于在windows下查看系统信息大家一定不

为什么低频信息描述了图像在光滑部位的整体灰度信息,而高频部分则反映了图像在边缘、噪声等细节方面的表现?

今天突然冒出来这个问题,为什么图像边缘是图像高频部分呢? 高频不应该是频率高的部分么?图像边缘应该是频率低的啊? 查了不少人的问答简单而言,是对频率的理解问题: 高频是指高的f,而f则可以理解特定的正弦波,频率越大,正弦波是不是变化得越快? 另附上高人解答: 冈萨雷斯版<图像处理>里面的解释非常形象:一个恰当的比喻是将傅里叶变换比作一个玻璃棱镜.棱镜是可以将光分解为不同颜色的物理仪器,每个成分的颜色由波长(或频率)来决定. 傅里叶变换可以看作是数学上的棱镜,将函数基于频率分解为不同的成分.当我