MSM短信发送过程

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


你可能感兴趣的:(thread,String,null,dialog,action,sms)