1. 点击发送按钮Src/com/android/mms/ui/ComposeMessageActivity.java
public void onClick(View v) {
if ((v == mSendButton) && isPreparedForSending()) {
confirmSendMessageIfNeeded(); //确认是否需要发送短信—-》
}
}
2.src/com/android/mms/ui/ComposeMessageActivity.java
private void confirmSendMessageIfNeeded() {
if (!isRecipientsEditorVisible()) { //编辑联系人不可见时,也就是给已存在会话的联系人发送短信时
sendMessage(true);
return;
}
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)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle(title)
.setMessage(R.string.invalid_recipient_message)
.setPositiveButton(R.string.try_to_send,
newSendIgnoreInvalidRecipientListener())
.setNegativeButton(R.string.no, new CancelSendingListener())
.show();
} else {//如果全是不合法的联系人,提示不能发送信息
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle(R.string.cannot_send_message)
.setMessage(R.string.cannot_send_message_reason)
.setPositiveButton(R.string.yes, new CancelSendingListener())
.show();
}
} else {//判断收件人没有问题,接着发送信息 --》
sendMessage(true);
}
}
3. src/com/android/mms/ui/ComposeMessageActivity.java
private void sendMessage(boolean bCheckEcmMode) {
Log.v(TAG, "sendMessage");
if (bCheckEcmMode) {
// TODO: expose this in telephony layer for SDK build
String inEcm = SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE); //判断电话是否处于紧急拨号模式,得到的inEcm一般为空
Log.v(TAG, "inEcm = " + inEcm);
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);
}
}
}
if (!mSendingMessage) {
// send can change the recipients. Make sure we remove the listeners firstand then add
// them back once the recipient list has settled.
removeRecipientsListeners(); //取消对收件人的监听
mWorkingMessage.send(); //发送信息—-》
mSentMessage = true;
mSendingMessage = true;
addRecipientsListeners(); //重新添加收件人监听
}
// But bail out if we are supposed to exit after the message is sent.
if (mExitOnSent) {//如果mExitOnSent为true,信息发送完成后退出Activity
finish();
}
}
4. src/com/android/mms/data/WorkingMessage.java
/**
* Send this message over the network. Will call back with onMessageSent() once
* it has been dispatched to the telephonystack. This WorkingMessage object is
* no longer useful after this method hasbeen called.
*/
public void send() {
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
LogTag.debug("send");
}
// Get ready to write to disk.
prepareForSave(true /* notify */);//主要做一下同步收件人和WorkingMessage,彩信时在准备其他一些东西
// We need the recipient list for both SMS and MMS.
final Conversation conv = mConversation;
String msgTxt = mText.toString();
Log.v(TAG, "msgText = " + msgTxt);
if (requiresMms() ||addressContainsEmailToMms(conv, msgTxt)) {
// 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.
final Uri mmsUri = mMessageUri;
final PduPersister persister = PduPersister.getPduPersister(mContext);
final SlideshowModel slideshow = mSlideshow;
final SendReq sendReq = makeSendReq(conv,mSubject);
// Do the dirty work of sending the message off of the main UI thread.
new Thread(new Runnable() {
public void run() {
// Make sure the text in slide 0 is no longer holding onto a reference to
// the text in the message text box.
slideshow.prepareForSend();
sendMmsWorker(conv, mmsUri,persister, slideshow, sendReq);
}
}).start();
} else {
// Same rules apply as above.
final String msgText = mText.toString();//取出短消息
Log.v(TAG, "msgText = " + msgText);
new Thread(new Runnable() {
public void run() {
preSendSmsWorker(conv, msgText);//发送信息--》
}
}).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;
}
5. src/com/android/mms/data/WorkingMessage.java
private void preSendSmsWorker(Conversation conv, StringmsgText) {
// If user tries to send the message, it's a signal the inputtedtext is what they wanted.
UserHappinessSignals.userAcceptedImeText(mContext);
mStatusListener.onPreMessageSent();//重置一些信息,比如清空输入内容框、一些监听等等
// Make sure we are still using the correct thread ID for our
// recipient set.
long threadId = conv.ensureThreadId();//新建获得会话线程ID
Log.v(TAG, "threadId = " + threadId);
final String semiSepRecipients =conv.getRecipients().serialize();
// just do a regular send. We're already on a non-ui thread so noneed to fire
// off another thread to do this work.
sendSmsWorker(msgText, semiSepRecipients, threadId);//发送信息----》
// Be paranoid and clean any draft SMS up.
deleteDraftSmsMessage(threadId);//删除草稿
}
6. src/com/android/mms/data/WorkingMessage.java
private void sendSmsWorker(String msgText, String semiSepRecipients, longthreaded) {
String[] dests = TextUtils.split(semiSepRecipients,“;”);
Log.v(TAG, “sendSmsWorker – semiSepRecipients is “ + semiSepRecipients);
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
LogTag.debug(“sendSmsWorker sending message”);
}
MessageSender sender = new SmsMessageSender(mContext, dests, msgText, threaded);
try {
sender.sendMessage(threadId);//根据ThreadID发送信息----》
// Make sure this thread isn't over the limits in message count
Recycler.getSmsRecycler().deleteOldMessagesByThreadId(mContext, threadId);
} catch (Exception e) {
Log.e(TAG, "Failed to send SMS message, threadId=" + threadId, e);
}
mStatusListener.onMessageSent();
}
7. src/com/android/mms/transaction/SmsMessageSender.java
public boolean sendMessage(long token) throwsMmsException {
// In order to send the message one by one, instead of sending now, themessage will split,
// and be put into the queue along with each destinations
return queueMessage(token);
}
8. src/com/android/mms/transaction/SmsMessageSender.java
private boolean queueMessage(long token) throwsMmsException {
if ((mMessageText == null) || (mNumberOfDests == 0)) {
// Don't try to send an empty message.
throw new MmsException("Null message body or dest.");
}
Log.v("SMsMessageSender", "queueMessage");
SharedPreferences prefs =PreferenceManager.getDefaultSharedPreferences(mContext);
boolean requestDeliveryReport =prefs.getBoolean(
MessagingPreferenceActivity.SMS_DELIVERY_REPORT_MODE,
DEFAULT_DELIVERY_REPORT_MODE);
Log.v("SmsMessageSender", "add Message to 'content://sms/queued'");
for (int i = 0; i < mNumberOfDests; i++) {//根据收件人数目分别建立短信放入发送队列
try {
Sms.addMessageToUri(mContext.getContentResolver(),
Uri.parse("content://sms/queued"), mDests[i],
mMessageText, null, mTimestamp,
true /* read */,
requestDeliveryReport,
mThreadId);
} catch (SQLiteException e) {
SqliteWrapper.checkSQLiteException(mContext, e);
}
}
// Notify the SmsReceiverService to send the message out
mContext.sendBroadcast(new Intent(SmsReceiverService.ACTION_SEND_MESSAGE,
null,
mContext,
SmsReceiver.class)); //通知SmsReceiverService来发送短信,传递参数ACTION_SEND_MESSAGE
return false;
}
9. src/com/android/mms/transaction/SmsReceiverService.java
/**
* Handle incoming transactionrequests.
* The incoming requests are initiatedby the MMSC Server or by the MMS Client itself.
*/
@Override
public void handleMessage(Message msg) {
int serviceId = msg.arg1;
Intent intent = (Intent)msg.obj;
if (intent != null) {
String action =intent.getAction();
int error = intent.getIntExtra("errorCode", 0);
if (MESSAGE_SENT_ACTION.equals(intent.getAction())){
handleSmsSent(intent,error);
} else if (SMS_RECEIVED_ACTION.equals(action)) {
handleSmsReceived(intent,error);
} else if (ACTION_BOOT_COMPLETED.equals(action)) {
handleBootCompleted();
} else if (TelephonyIntents.ACTION_SERVICE_STATE_CHANGED.equals(action)){
handleServiceStateChanged(intent);
} else if (ACTION_SEND_MESSAGE.endsWith(action)) {
handleSendMessage();//处理发送信息
}
}
// NOTE: We MUST not call stopSelf() directly, since we need to
// make sure the wake lock acquired by AlertReceiver is released.
SmsReceiver.finishStartingService(SmsReceiverService.this, serviceId);
}
}
10. src/com/android/mms/transaction/SmsReceiverService.java
private void handleSendMessage(){
Log.v(TAG, "handleSendMessage");
if (!mSending) {//如果没有发送,则准备发送
sendFirstQueuedMessage();
}
}
11. src/com/android/mms/transaction/SmsReceiverService.java
public synchronized void sendFirstQueuedMessage() {
Log.v(TAG, "sendFirstQueuedMessage");
boolean success = true;
// get all the queued messages from the database
final Uri uri = Uri.parse("content://sms/queued");
ContentResolver resolver =getContentResolver();
//查询队列中的信息,包括上次没有发送出去存放在发送队列的信息
Cursor c = SqliteWrapper.query(this, resolver, uri,
SEND_PROJECTION, null, null, "date ASC"); // date ASC so we send out in
// same order the user tried
// to send messages.
if (c != null) {
try {
if (c.moveToFirst()) {
String msgText =c.getString(SEND_COLUMN_BODY);
String address =c.getString(SEND_COLUMN_ADDRESS);
int threadId = c.getInt(SEND_COLUMN_THREAD_ID);
int status = c.getInt(SEND_COLUMN_STATUS);
Log.v(TAG, "address = " + address);
Log.v(TAG, "msgText = " + msgText);
Log.v(TAG, "status = " + status);
int msgId = c.getInt(SEND_COLUMN_ID);
Uri msgUri = ContentUris.withAppendedId(Sms.CONTENT_URI,msgId);
Log.v(TAG, "msgId = " + msgId);
SmsMessageSender sender = newSmsSingleRecipientSender(this,
address, msgText,threadId, status == Sms.STATUS_PENDING,
msgUri);
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
Log.v(TAG, "sendFirstQueuedMessage " + msgUri +
", address: " + address +
", threadId: " + threadId +
", body: " + msgText);
}
try {
sender.sendMessage(SendingProgressTokenManager.NO_TOKEN);//进行单个信息发送
mSending = true;
} catch (MmsExceptione) {
Log.e(TAG, "sendFirstQueuedMessage: failed to send message" + msgUri
+ ", caught ", e);
success = false;
}
}
} finally {
c.close();
}
}
if (success) {
// We successfully sent all the messages in the queue. We don't need to
// be notified of any service changes any longer.
unRegisterForServiceStateChanges();
}
转载自:http://blog.csdn.net/lijinwei_123/article/details/6591900