SMS发送接收流程

来源:互联网 发布:网络工程规划与设计 编辑:程序博客网 时间:2024/06/10 10:47

1.短信发送的起点是在短信编辑界面,点击发送按钮开始的

public class ComposeMessageActivity extends Activity  ...{....    public void sendMessage(boolean bCheckEcmMode) {                 ....         //这里面准备发送的数据处理,比如生成PDU数据,存储到数据            mWorkingMessage.send(mDebugRecipients, mSelectedSubId);          }

这里写图片描述

mWorkingMessage中具体发送短信的工作在preSendSmsWorker方法里面
private void preSendSmsWorker(Conversation conv, String msgText, String recipientsInUI,
int subId, boolean hasBeenSplit) {
// just do a regular send. We’re already on a non­ui thread so no need to fire
// off another thread to do this work.
/// M: Code analyze 047, For new feature ALPS00316567, add a parameter for msim . @{
sendSmsWorker是最主要的类,做了实际的发送工作,但他里面不是立即发送短信,而是发送短信的请求封装成SmsMessageSender,
sendSmsWorker(msgText, semiSepRecipients, threadId, subId);
/// @}

} .
SmsReceiverService
SmsMessageSender*******************************************
将待发送的短信存储到数据库表格中,content://sms/queued
然后再启动服务SmsReceiverService,让服务去单个发送每一条短信,SmsReceiverService重待发送短信表格中取出一条短信,然后交由
SmsSingleRecipientSender去发送。

这里写图片描述

MessageSender sender = new SmsMessageSender(mActivity, dests, msgText, threadId, subId); 短信发送处理   public boolean sendMessage(long token) throws MmsException {号码处理,将其中的空格去除。得到有效的发送号码。生成2个广播1.发送报告广播,2.发送短信广播最终调用系统接口SmsManager smsManager = SmsManager.getSmsManagerForSubscriptionId(mSubId);SmsManager***************************************************************************************************    public void sendMultipartTextMessage(            String destinationAddress, String scAddress, ArrayList<String> parts,            ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {         if (parts.size() > 1) {            try {                ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));                if (iccISms != null) {                    iccISms.sendMultipartText(destinationAddress, scAddress, parts,                            sentIntents, deliveryIntents);                }            } catch (RemoteException ex) {                // ignore it            }        } else {            PendingIntent sentIntent = null;            PendingIntent deliveryIntent = null;            if (sentIntents != null && sentIntents.size() > 0) {                sentIntent = sentIntents.get(0);            }            if (deliveryIntents != null && deliveryIntents.size() > 0) {                deliveryIntent = deliveryIntents.get(0);            }            sendTextMessage(destinationAddress, scAddress, parts.get(0),                    sentIntent, deliveryIntent);        }****************************************************************************ISms.Stub.asInterface(ServiceManager.getService("isms"));,这个的服务类型有多种,发送彩信********************************************************************************************sendMmsWorker(spliter.getMMSConversation(),                                mmsUri, persister, slideshow, sendReq, subId);/// M: Code analyze 047, For new feature ALPS00316567, add a parameter for msim . @{    private void sendSmsWorker(String msgText, String semiSepRecipients, long threadId, int subId) {    /// @}        String[] dests = TextUtils.split(semiSepRecipients, ";"if (LogTag.VERBOSE || Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {            Log.d(LogTag.TRANSACTION, "sendSmsWorker sending message: recipients=" +                    semiSepRecipients + ", threadId=" + threadId);        }        MessageSender sender = new SmsMessageSender(mActivity, dests, msgText, threadId, subId);        try {            sender.sendMessage(threadId);            // Make sure this thread isn't over the limits in message count            Recycler.getSmsRecycler().deleteOldMessagesByThreadId(mActivity, threadId);        } catch (Exception e) {            Log.e(TAG, "Failed to send SMS message, threadId=" + threadId, e);        }        mStatusListener.onMessageSent();        MmsWidgetProvider.notifyDatasetChanged(mActivity);    }   public boolean sendMessage(long token) throws MmsException {        // In order to send the message one by one, instead of sending now, the message will split,        // and be put into the queue along with each destinations        return queueMessage(token);    }    private boolean queueMessage(long token) throws MmsException {        /// M:        MmsLog.v(MmsApp.TXN_TAG, "queueMessage()"if ((mMessageText == null) || mMessageText.isEmpty() || (mNumberOfDests == 0)) {            // Don't try to send an empty message.            throw new MmsException("Null message body or dest.");        }        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);        boolean requestDeliveryReport = prefs.getBoolean(mSubId + "_" + SmsPreferenceActivity.SMS_DELIVERY_REPORT_MODE,                DEFAULT_DELIVERY_REPORT_MODE);        MmsLog.d(MmsApp.TXN_TAG, "SMS DR request=" + requestDeliveryReport);        /// @}        Uri smsUri = null;//star os add by liuweibo        long timeStamp = System.currentTimeMillis();        for (int i = 0; i < mNumberOfDests; i++) {            try {                if (LogTag.DEBUG_SEND) {                    Log.v(TAG, "queueMessage mDests[i]: " + mDests[i] + " mThreadId: " + mThreadId);                }                 smsUri = mOpSmsMessageSender.queueMessage(mNumberOfDests,//star os modify by liuweibo                        mContext.getContentResolver(), mDests[i], mMessageText, mTimestamp,                        requestDeliveryReport, mThreadId, mSubId, ­timeStamp);                if (smsUri == null) {                    smsUri=Sms.addMessageToUri(mSubId,//star os modify by liuweibo                            mContext.getContentResolver(),                            Uri.parse("content://sms/queued"), mDests[i],                            mMessageText, null, mTimestamp,                            true /* read */,                            requestDeliveryReport,                            mThreadId);                }                //star os add start by liuweibo                Intent sentIt = new Intent("delay_send_sms", null, mContext,                                                SmsReceiver.class);                long msgId = Integer.valueOf(smsUri.toString().substring(14));                sentIt.putExtra("message_id", msgId);                mContext.sendBroadcast(sentIt);                //star os add end by liuweibo            } catch (SQLiteException e) {                if (LogTag.DEBUG_SEND) {                    Log.e(TAG, "queueMessage SQLiteException", e);                }                SqliteWrapper.checkSQLiteException(mContext, e);            }        }        // Notify the SmsReceiverService to send the message out       //star os del start by liuweibo        /*        mContext.sendBroadcast(new Intent(SmsReceiverService.ACTION_SEND_MESSAGE,                null,                mContext,                SmsReceiver.class));        */        //star os del end by liuweibo        return false;    } 

这里写图片描述

/frameworks/opt/telephony/src/java/android/telephony/SmsManager.java
sendStoredMultimediaMessage/**  * Send a system stored MMS message  *  * This is used for sending a previously sent, but failed-to-send, message or  * for sending a text message that has been stored as a draft.  *  * @param messageUri the URI of the stored message  * @param configOverrides the carrier-specific messaging configuration values to override for  *  sending the message.  * @param sentIntent if not NULL this <code>PendingIntent</code> is  *  broadcast when the message is successfully sent, or failed  * @throws IllegalArgumentException if messageUri is empty  * {@hide}  */public void sendStoredMultimediaMessage(Uri messageUri, Bundle configOverrides,PendingIntent sentIntent) {if (messageUri == null) {throw new IllegalArgumentException("Empty message URI");}try {IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));if (iMms != null) {iMms.sendStoredMessage(getSubscriptionId(), ActivityThread.currentPackageName(), messageUri,configOverrides, sentIntent);}} catch (RemoteException ex) {// ignore it}}短信接收***********************************************************************************首先系统发出android.provider.Telephony.Sms.Intents.SMS_DELIVER_ACTION广播,然后SmsReceiver接收,接收后启动service SmsReceiverService处理

这里写图片描述

系统是什么地方发送广播:


/frameworks/opt/telephony/src/java/com/android/internal/telephony/InboundSmsHandler.java

 /**     * In the delivering state, the inbound SMS is processed and stored in the raw table.     * The message is acknowledged before we exit this state. If there is a message to broadcast,     * transition to {@link WaitingState} state to send the ordered broadcast and wait for the     * results. When all messages have been processed, the halting state will release the wakelock.     */    private class DeliveringState extends State {    ****        @Override        public boolean processMessage(Message msg) {            log("DeliveringState.processMessage:" + msg.what);            log("DeliveringState.processMessage:" + msg.what);            switch (msg.what) {                case EVENT_BROADCAST_SMS:                    // if any broadcasts were sent, transition to waiting state                    InboundSmsTracker inboundSmsTracker = (InboundSmsTracker) msg.obj;                    if (processMessagePart(inboundSmsTracker)) {                        transitionTo(mWaitingState);                    } else {                        // if event is sent from SmsBroadcastUndelivered.broadcastSms(), and                        // processMessagePart() returns false, the state machine will be stuck in                        // DeliveringState until next message is received. Send message to                        // transition to idle to avoid that so that wakelock can be released                        log("No broadcast sent on processing EVENT_BROADCAST_SMS in Delivering " +                                "state. Return to Idle state");                        sendMessage(EVENT_RETURN_TO_IDLE);                    }                    return HANDLED;            ****    private boolean processMessagePart(InboundSmsTracker tracker) {    ****            dispatchSmsDeliveryIntent(pdus, tracker.getFormat(), destPort, resultReceiver,                    IConcatenatedSmsFwkExt.UPLOAD_FLAG_NONE);       /////    private void dispatchSmsDeliveryIntent(byte[][] pdus, String format, int destPort,            BroadcastReceiver resultReceiver, int longSmsUploadFlag) {    // MTK­END        Intent intent = new Intent();        intent.putExtra("pdus", pdus);        intent.putExtra("format", format);        if (destPort == ­1) {            intent.setAction(Intents.SMS_DELIVER_ACTION);        ***        dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,                AppOpsManager.OP_RECEIVE_SMS, options, resultReceiver, UserHandle.SYSTEM);­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­    public void dispatchIntent(Intent intent, String permission, int appOp,            Bundle opts, BroadcastReceiver resultReceiver, UserHandle user) {        intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);        ******            mContext.sendOrderedBroadcastAsUser(intent, user, permission, appOp, opts,                    resultReceiver, getHandler(), Activity.RESULT_OK, null, null);到这里,消息广播就发送出去了。

这里写图片描述

将PDU数据插入到raw表中    /**     * Insert a message PDU into the raw table so we can acknowledge it immediately.     * If the device crashes before the broadcast to listeners completes, it will be delivered     * from the raw table on the next device boot. For single­part messages, the deleteWhere     * and deleteWhereArgs fields of the tracker will be set to delete the correct row after     * the ordered broadcast completes.     *     * @param tracker the tracker to add to the raw table     * @return true on success; false on failure to write to database     */    private int addTrackerToRawTable(InboundSmsTracker tracker, boolean deDup) {

短信接收时序图:
这里写图片描述

0 0
原创粉丝点击