- 发送前的校验
从短信的点击按钮开始着手:
// packages/apps/Mms/src/com/android/mms/ui/ComposeMessageActivity.java
@Override
public void onClick(View v) {
mIsRTL = (v.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
if ((v == mSendButtonSms || v == mSendButtonMms) && isPreparedForSending()) {
... ...
if (mShowTwoButtons) {
confirmSendMessageIfNeeded(SubscriptionManager.getSubId(PhoneConstants.SUB1)[0]);
} else {
if (mIsRcsEnabled) {
if (RcsUtils.isRcsOnline()
&& ((mWorkingMessage.getCacheRcsMessage() || (!mWorkingMessage
.requiresMms() && mWorkingMessage.hasText())))) {
rcsSend();
} else {
if (mConversation.isGroupChat()) {
toast(R.string.rcs_offline_unable_to_send);
return;
}
if (mIsBurnMessage) {
toast(R.string.rcs_not_online_can_not_send_burn_message);
mIsBurnMessage = false;
return;
} else {
confirmSendMessageIfNeeded();
}
}
} else {
confirmSendMessageIfNeeded();
}
}
}
... ...
}
首先判断是否是双卡的情况,双卡的情况下通过SubId来区分哪张卡;单卡则判断是否启用RCS(rcs默认是关闭的,配置开关的路径:/Mms/res/values/config.xml config_rcs_sms_version)没有启用会执行confirmSendMessageIfNeeded对收件人地址信息确认.
private void confirmSendMessageIfNeeded() {
LogTag.debugD("confirmSendMessageIfNeeded");
if (mRcsShareVcard) {
mWorkingMessage.setRcsType(RcsUtils.RCS_MSG_TYPE_VCARD);
mRcsShareVcard = false;
}
int slot = SubscriptionManager.getSlotId(
SmsManager.getDefault().getDefaultSmsSubscriptionId());
if ((TelephonyManager.getDefault().isMultiSimEnabled() &&
isLTEOnlyMode(slot))
|| (!TelephonyManager.getDefault().isMultiSimEnabled()
&& isLTEOnlyMode())) {
showDisableLTEOnlyDialog(slot);
LogTag.debugD("return for disable LTEOnly");
return;
}
boolean isMms = mWorkingMessage.requiresMms();
int defaultSubId = SubscriptionManager.getDefaultSmsSubscriptionId();
if (!isRecipientsEditorVisible()) {
if (TelephonyManager.getDefault().isMultiSimEnabled()) {
if ((TelephonyManager.getDefault().getPhoneCount()) > 1 &&
MessageUtils.isMsimIccCardActive()) {
if(SmsManager.getDefault().isSMSPromptEnabled()) {
launchMsimDialog(true, isMms);
} else {
sendMsimMessageNotPrompt(true, isMms, defaultSubId);
}
} else {
sendMsimMessageNotPrompt(true, isMms, defaultSubId);
}
} else if (isMmsWithMobileDataOff(isMms, defaultSubId)) {
showMobileDataDisabledDialog();
} else {
sendMessage(true);
}
return;
}
// 判断收件人地址是否有效
if (mRecipientsEditor.hasInvalidRecipient(isMms)) {
showInvalidRecipientDialog();
} else if (TelephonyManager.getDefault().isMultiSimEnabled()) { // 判断是否是双卡的情况
if ((TelephonyManager.getDefault().getPhoneCount()) > 1 &&
MessageUtils.isMsimIccCardActive()) {
if(SmsManager.getDefault().isSMSPromptEnabled()) {
launchMsimDialog(true, isMms);
} else {
sendMsimMessageNotPrompt(true, isMms, defaultSubId);
}
} else {
sendMsimMessageNotPrompt(true, isMms, defaultSubId);
}
} else if (isMmsWithMobileDataOff(isMms, defaultSubId)) { // 判断是否是彩信,并且数据流量是否打开
showMobileDataDisabledDialog(defaultSubId);
} else {
if (!TextUtils.isEmpty(getString(R.string.mms_recipient_Limit))
&& isMms
&& checkForMmsRecipients(getString(R.string.mms_recipient_Limit), true)) {
return;
}
//获取收件人地址,发送
// The recipients editor is still open. Make sure we use what's showing there
// as the destination.
ContactList contacts = mRecipientsEditor.constructContactsFromInput(false);
mDebugRecipients = contacts.serialize();
sendMessage(true);
}
}
这里是对收件人地址检测等一些状态判断,最后通过sendMessage()继续发送逻辑.
private void sendMessage(boolean bCheckEcmMode) {
LogTag.debugD("sendMessage true");
if (mIsRcsEnabled && hasConvertRcsAttachmentToMmsAndSent()) {
return;
}
// Check message size, if >= max message size, do not send message.
if(checkMessageSizeExceeded()){
LogTag.debugD("MessageSizeExceeded");
return;
}
// 检查当前是否是ECM模式
if (bCheckEcmMode) {
// TODO: expose this in telephony layer for SDK build
String inEcm = SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE);
if (Boolean.parseBoolean(inEcm)) {
try {
startActivityForResult(
new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null),
REQUEST_CODE_ECM_EXIT_DIALOG);
return;
} catch (ActivityNotFoundException e) {
// continue to send message
Log.e(TAG, "Cannot find EmergencyCallbackModeExitDialog", e);
}
}
}
// Make the recipients editor lost focus, recipients editor will shrink
// and filter useless char in recipients to avoid send sms failed.
if (isRecipientsEditorVisible()
&& mRecipientsEditor.isFocused()
&& !mWorkingMessage.requiresMms()) {
mTextEditor.requestFocus();
}
// 判断是否有短信正在发送
if (!mSendingMessage) {
if (LogTag.SEVERE_WARNING) {
String sendingRecipients = mConversation.getRecipients().serialize();
if (!sendingRecipients.equals(mDebugRecipients)) {
String workingRecipients = mWorkingMessage.getWorkingRecipients();
if (workingRecipients != null && !mDebugRecipients.equals(workingRecipients)) {
LogTag.warnPossibleRecipientMismatch("ComposeMessageActivity.sendMessage" +
" recipients in window: \"" +
mDebugRecipients + "\" differ from recipients from conv: \"" +
sendingRecipients + "\" and working recipients: " +
workingRecipients, this);
}
}
sanityCheckConversation();
}
// send can change the recipients. Make sure we remove the listeners first and then add
// them back once the recipient list has settled.
removeRecipientsListeners();
// 判断是否为多个联系人,然后进入WorkingMessage执行发送
if (mWorkingMessage.getResendMultiRecipients()) {
// If resend sms recipient is more than one, use mResendSmsRecipient
LogTag.debugD("mWorkingMessage send mResendSmsRecipient=" + mResendSmsRecipient);
mWorkingMessage.send(mResendSmsRecipient);
} else {
LogTag.debugD("mWorkingMessage send mDebugRecipients=" + mDebugRecipients);
mWorkingMessage.send(mDebugRecipients);
}
mSentMessage = true;
mSendingMessage = true;
addRecipientsListeners();
mScrollOnSend = true; // in the next onQueryComplete, scroll the list to the end.
}
// But bail out if we are supposed to exit after the message is sent.
if (mSendDiscreetMode || MessageUtils.isMailboxMode()) {
finish();
}
}
WorkingMessage包含所有用户编辑短信相关的状态,这里判断如果没有短信正在发送,则通过WorkingMessage发送短信.
/**
* Send this message over the network. Will call back with onMessageSent() once
* it has been dispatched to the telephony stack. This WorkingMessage object is
* no longer useful after this method has been called.
*
* @throws ContentRestrictionException if sending an MMS and uaProfUrl is not defined
* in mms_config.xml.
*/
public void send(final String recipientsInUI) {
long origThreadId = mConversation.getThreadId();
LogTag.debugD("send origThreadId: " + origThreadId);
removeSubjectIfEmpty(true /* notify */);
// Get ready to write to disk.
prepareForSave(true /* notify */);
// Make sure the mConversation has Recipients
checkConversationHasRecipients(recipientsInUI);
// We need the recipient list for both SMS and MMS.
final Conversation conv = mConversation;
String msgTxt = mText.toString();
if (MmsConfig.isRcsEnabled() && shouldSendMessageWithRcsPolicy()) {
sendRcsMessage(recipientsInUI);
return;
}
if (requiresMms() || addressContainsEmailToMms(conv, msgTxt)) { // 发送彩信
// uaProfUrl setting in mms_config.xml must be present to send an MMS.
// However, SMS service will still work in the absence of a uaProfUrl address.
if (MmsConfig.getUaProfUrl() == null) {
String err = "WorkingMessage.send MMS sending failure. mms_config.xml is " +
"missing uaProfUrl setting. uaProfUrl is required for MMS service, " +
"but can be absent for SMS.";
RuntimeException ex = new NullPointerException(err);
Log.e(TAG, err, ex);
// now, let's just crash.
throw ex;
}
// Make local copies of the bits we need for sending a message,
// because we will be doing it off of the main thread, which will
// immediately continue on to resetting some of this state.