《Android發短信底層源碼(android5.1)解析》---主要解析SMSDispatcher發短信部分源碼

解析android底層發短信相關源碼,包括短信的發送,以及RIL層返回結果的處理。如有錯誤請更正。本文從SMSDispatcher開始分析,不包括上層代碼分析。

SMSDispatcher相關說明

SMSDispatcher的子類主要有GsmSMSDispatcher與CdmaSMSDispatcher。ImsSMSDispatcher相當於是對上面兩個子類的一個包裝,上層調用時主要調用ImsSMSDispatcher中的方法。ImsSMSDispatcher中再去選擇調用的是Gsm還是Cdma中的方法。

GsmSMSDispatcher發短信解析(主要針對文本短信)

GsmSMSDispatcher.sendSms開始短信的發送。真正發送通過調用sendSmsByPstn

關鍵代碼

if (tracker.mRetryCount == 0 && tracker.mExpectMore) {
    // 發送失敗時,原因同時有多條短信在發送則調用該方法
    // EVENT_SEND_LIMIT_REACHED_CONFIRMATION
    mCi.sendSMSExpectMore(IccUtils.bytesToHexString(smsc),
            IccUtils.bytesToHexString(pdu), reply);
} else {
    // 正常發送
    mCi.sendSMS(IccUtils.bytesToHexString(smsc),
            IccUtils.bytesToHexString(pdu), reply);
}

發送成功解析

主要發送成功,失敗(多條短信等)
發送成功時會發送上面的reply消息。
關鍵代碼在handleMessage中。成功後會調用對應的SentIntent中的send方法

關鍵代碼

if (mSentIntent != null) {
    try {
        // Extra information to send with the sent intent
        Intent fillIn = new Intent();
        if (mMessageUri != null) {
            // Pass this to SMS apps so that they know where it is stored
            fillIn.putExtra("uri", mMessageUri.toString());
        }
        if (mUnsentPartCount != null && isSinglePartOrLastPart) {
            // Is multipart and last part
            fillIn.putExtra(SEND_NEXT_MSG_EXTRA, true);
        }
        // 發送成功報告
        mSentIntent.send(context, Activity.RESULT_OK, fillIn);
    } catch (CanceledException ex) {
        Rlog.e(TAG, "Failed to send result");
    }
}

關於送達報告的執行,要在SMSDispatcher創建的時候在CommandsInterface中進行註冊。告訴底層RIL送到後發送的消息。

關鍵代碼

 public GsmSMSDispatcher(PhoneBase phone, SmsUsageMonitor usageMonitor,
        ImsSMSDispatcher imsSMSDispatcher,
        GsmInboundSmsHandler gsmInboundSmsHandler) {
    super(phone, usageMonitor, imsSMSDispatcher);
    // 註冊送達報告消息
    mCi.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null);
    mGsmInboundSmsHandler = gsmInboundSmsHandler;
    mUiccController = UiccController.getInstance();
    mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
    Rlog.d(TAG, "GsmSMSDispatcher created");
}
// 送達報告執行部分
PendingIntent intent = tracker.mDeliveryIntent;
Intent fillIn = new Intent();
fillIn.putExtra("pdu", IccUtils.hexStringToBytes(pduString));
fillIn.putExtra("format", getFormat());
try {
    intent.send(mContext, Activity.RESULT_OK, fillIn);
} catch (CanceledException ex) {}

發送失敗解析

如果發送失敗主要還是進行重試,重試MAX_SEND_RETRIES次。重試的時候會有時間延時SEND_RETRY_DELAY

關鍵代碼

if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) {
    tracker.onFailed(mContext, getNotInServiceError(ss), 0/*errorCode*/);
} else if ((((CommandException)(ar.exception)).getCommandError()
        == CommandException.Error.SMS_FAIL_RETRY) &&
       tracker.mRetryCount < MAX_SEND_RETRIES) {
    tracker.mRetryCount++;
    Message retryMsg = obtainMessage(EVENT_SEND_RETRY, tracker);
    // 發送重試消息,進行重試
    sendMessageDelayed(retryMsg, SEND_RETRY_DELAY);
}

// 這部分代碼不知道是不是判斷電話是不是在使用,有待驗證
int ss = mPhone.getServiceState().getState();

if ( tracker.mImsRetry > 0 && ss != ServiceState.STATE_IN_SERVICE) {
    // This is retry after failure over IMS but voice is not available.
    // Set retry to max allowed, so no retry is sent and
    //   cause RESULT_ERROR_GENERIC_FAILURE to be returned to app.
    tracker.mRetryCount = MAX_SEND_RETRIES;

    Rlog.d(TAG, "handleSendComplete: Skipping retry: "
    +" isIms()="+isIms()
    +" mRetryCount="+tracker.mRetryCount
    +" mImsRetry="+tracker.mImsRetry
    +" mMessageRef="+tracker.mMessageRef
    +" SS= "+mPhone.getServiceState().getState());
}

要想知道失敗原因還得細讀失敗時候的處理。

發佈了170 篇原創文章 · 獲贊 56 · 訪問量 38萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章