我们先来看最简单的流程入手分析,即收件人只有一个,而且不是长短信的情况。
一、地址有效性检测
@ComposeMessageActivity.java
public void onClick(View v) {
if ((v == mSendButtonSms || v == mSendButtonMms) && isPreparedForSending()) {
//确认发送
confirmSendMessageIfNeeded();
} else if ((v == mRecipientsPicker)) {
launchMultiplePhonePicker();
}
}
然后进行
收件人地址信息的确认:
private void confirmSendMessageIfNeeded() {
if (!isRecipientsEditorVisible()) {
//当前的收件人编辑框不可见,说明所发送的对象已经存在短信的会话,也说明当前的收件人地址是ok的
sendMessage(true);
return;
}
//判断是否为MMS
boolean isMms = mWorkingMessage.requiresMms();
if (mRecipientsEditor.hasInvalidRecipient(isMms)) {
//当前的收件人列表中包含无效地址
if (mRecipientsEditor.hasValidRecipient(isMms)) {
//当前的收件人列表中有无效地址和有效地址,提示用户是否忽略,只发送有效的地址
String title = getResourcesString(R.string.has_invalid_recipient,
mRecipientsEditor.formatInvalidNumbers(isMms));
new AlertDialog.Builder(this)
.setTitle(title)
.setMessage(R.string.invalid_recipient_message)
.setPositiveButton(R.string.try_to_send,
new SendIgnoreInvalidRecipientListener())
.setNegativeButton(R.string.no, new CancelSendingListener())
.show();
} else {
//当前的收件人列表中的地址全部无效,取消发送,提示用户
new AlertDialog.Builder(this)
.setTitle(R.string.cannot_send_message)
.setMessage(R.string.cannot_send_message_reason)
.setPositiveButton(R.string.yes, new CancelSendingListener())
.show();
}
} else {
//收件人地址都是有效的,发送
ContactList contacts = mRecipientsEditor.constructContactsFromInput(false);
mDebugRecipients = contacts.serialize();
sendMessage(true);
}
}
经过地址有效性检测后,通过sendMessage()继续流程,这里传递的bCheckEcmMode参数代表是否检查当前Phone的状态,
处于紧急状态时无法发送短信:
private void sendMessage(boolean bCheckEcmMode) {
if (bCheckEcmMode) {
//判断当前是否为紧急呼叫模式
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) {
Log.e(TAG, "Cannot find EmergencyCallbackModeExitDialog", e);
}
}
}
//判断当前是否有短信正在发送
if (!mSendingMessage) {
//重置收件人控件的监听器
removeRecipientsListeners();
//进入WorkingMessage处理流程
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) {
finish();
}
}
二、创建短彩信的发送线程
@WorkingMessage.java
public void send(final String recipientsInUI) {
long origThreadId = mConversation.getThreadId();
removeSubjectIfEmpty(true /* notify */);
prepareForSave(true /* notify */);
//拿到当前的会话
final Conversation conv = mConversation;
String msgTxt = mText.toString();
if (requiresMms() || addressContainsEmailToMms(conv, msgTxt)) {
//彩信发送
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;
}
final Uri mmsUri = mMessageUri;
final PduPersister persister = PduPersister.getPduPersister(mActivity);
final SlideshowModel slideshow = mSlideshow;
final CharSequence subject = mSubject;
final boolean textOnly = mAttachmentType == TEXT;
//彩信发送线程
new Thread(new Runnable() {
@Override
public void run() {
final SendReq sendReq = makeSendReq(conv, subject);
slideshow.prepareForSend();
sendMmsWorker(conv, mmsUri, persister, slideshow, sendReq, textOnly);
updateSendStats(conv);
}
}, "WorkingMessage.send MMS").start();
} else {
//短信发送流程
final String msgText = mText.toString();
new Thread(new Runnable() {
@Override
public void run() {
preSendSmsWorker(conv, msgText, recipientsInUI);
updateSendStats(conv);
}
}, "WorkingMessage.send SMS").start();
}
// update the Recipient cache with the new to address, if it's different
RecipientIdCache.updateNumbers(conv.getThreadId(), conv.getRecipients());
// Mark the message as discarded because it is "off the market" after being sent.
mDiscarded = true;
}
在上面的send流程中,WorkingMessage对短彩信进行分类,
分别创建子线程进行发送,本节我们只关注短信流程,他是在preSendSmsWorker()中被发送的:
private void preSendSmsWorker(Conversation conv, String msgText, String recipientsInUI) {
UserHappinessSignals.userAcceptedImeText(mActivity);
//UI刷新
mStatusListener.onPreMessageSent();
//获取初始的线程ID
long origThreadId = conv.getThreadId();
//获取分配的线程ID
lon