解析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());
}
要想知道失敗原因還得細讀失敗時候的處理。