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