Android 短信发送流程

短信发送Framework流程,源代码的版本是4.4

1、通过Mms源代码可以知道短信发送最后调用的关键api如下:

SmsSingleRecipientSender.java

SmsManager smsManager = SmsManager.getDefault();
...
try {
            smsManager.sendMultipartTextMessage(mDest, mServiceCenter, messages, sentIntents, deliveryIntents);
        } catch (Exception ex) {
            Log.e(TAG, "SmsMessageSender.sendMessage: caught", ex);
            throw new MmsException("SmsMessageSender.sendMessage: caught " + ex +
                    " from SmsManager.sendTextMessage()");
        }
...

smsManager对应的文件是SmsManager.java

2、SmsManager源代码路径是frameworks/opt/telephony/src/java/android/telephony/gsm/SmsManager.java

SmsManager这里用了单例模式初始化

/** Singleton object constructed during class initialization. */
    private static final SmsManager sInstance = new SmsManager();
/**
     * Get the default instance of the SmsManager
     *
     * @return the default instance of the SmsManager
     */
    public static SmsManager getDefault() {
        return sInstance;
    }
sendMultipartTextMessage的实现如下:

public void sendMultipartTextMessage(
            String destinationAddress, String scAddress, ArrayList<String> parts,
            ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
        if (TextUtils.isEmpty(destinationAddress)) {
            throw new IllegalArgumentException("Invalid destinationAddress");
        }
        if (parts == null || parts.size() < 1) {
            throw new IllegalArgumentException("Invalid message body");
        }


        if (parts.size() > 1) {
            try {
                ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
                if (iccISms != null) {
                    iccISms.sendMultipartText(ActivityThread.currentPackageName(),
                            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);
        }
    }

如果短信的内容被划分成了多个部分,将进入icc.sendMultipartText(),即如下

 try {
                ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
                if (iccISms != null) {
                    iccISms.sendMultipartText(ActivityThread.currentPackageName(),
                            destinationAddress, scAddress, parts,
                            sentIntents, deliveryIntents);
                }
            } catch (RemoteException ex) {
                // ignore it
            }
如果短信的内容只有一部分,则继续调用sendTextMessage(),即如下

	    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);
下面的流程主要针对sendTextMessage( )分析,sendMultipartText到此为止。

短信在发送之前会检查发送字符串是否超过最大长度,如果超过会被划分成几部分,对应这里的ArrayList<string> parts,

划分的具体实现对应smsManager.divideMessage(mMsgText)

    /**
     * Divide a message text into several fragments, none bigger than
     * the maximum SMS message size.
     *
     * @param text the original message.  Must not be null.
     * @return an <code>ArrayList</code> of strings that, in order,
     *   comprise the original message
     *
     * @throws IllegalArgumentException if text is null
     */
    public ArrayList<String> divideMessage(String text) {
        if (null == text) {
            throw new IllegalArgumentException("text is null");
        }
        return SmsMessage.fragmentText(text);
    }

很明显这里调用SmsMessage.fragmentText()

SmsMessage的路径是frameworks/opt/telephony/src/java/android/telephony/SmsMessage.java

fragmentText的具体实现如下:

    /**
     * Divide a message text into several fragments, none bigger than
     * the maximum SMS message text size.
     *
     * @param text text, must not be null.
     * @return an <code>ArrayList</code> of strings that, in order,
     *   comprise the original msg text
     *
     * @hide
     */
    public static ArrayList<String> fragmentText(String text) {
        // This function is for MO SMS
        TextEncodingDetails ted = (useCdmaFormatForMoSms()) ?
            com.android.internal.telephony.cdma.SmsMessage.calculateLength(text, false) :
            com.android.internal.telephony.gsm.SmsMessage.calculateLength(text, false);

        // TODO(cleanup): The code here could be rolled into the logic
        // below cleanly if these MAX_* constants were defined more
        // flexibly...

        int limit;
        if (ted.codeUnitSize == SmsConstants.ENCODING_7BIT) {
            int udhLength;
            if (ted.languageTable != 0 && ted.languageShiftTable != 0) {
                udhLength = GsmAlphabet.UDH_SEPTET_COST_TWO_SHIFT_TABLES;
            } else if (ted.languageTable != 0 || ted.languageShiftTable != 0) {
                udhLength = GsmAlphabet.UDH_SEPTET_COST_ONE_SHIFT_TABLE;
            } else {
                udhLength = 0;
            }

            if (ted.msgCount > 1) {
                udhLength += GsmAlphabet.UDH_SEPTET_COST_CONCATENATED_MESSAGE;
            }

            if (udhLength != 0) {
                udhLength += GsmAlphabet.UDH_SEPTET_COST_LENGTH;
            }

            limit = SmsConstants.MAX_USER_DATA_SEPTETS - udhLength;
        } else {
            if (ted.msgCount > 1) {
                limit = SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER;
            } else {
                limit = SmsConstants.MAX_USER_DATA_BYTES;
            }
        }

        int pos = 0;  // Index in code units.
        int textLen = text.length();
        ArrayList<String> result = new ArrayList<String>(ted.msgCount);
        while (pos < textLen) {
            int nextPos = 0;  // Counts code units.
            if (ted.codeUnitSize == SmsConstants.ENCODING_7BIT) {
                if (useCdmaFormatForMoSms() && ted.msgCount == 1) {
                    // For a singleton CDMA message, the encoding must be ASCII...
                    nextPos = pos + Math.min(limit, textLen - pos);
                } else {
                    // For multi-segment messages, CDMA 7bit equals GSM 7bit encoding (EMS mode).
                    nextPos = GsmAlphabet.findGsmSeptetLimitIndex(text, pos, limit,
                            ted.languageTable, ted.languageShiftTable);
                }
            } else {  // Assume unicode.
                nextPos = pos + Math.min(limit / 2, textLen - pos);
            }
            if ((nextPos <= pos) || (nextPos > textLen)) {
                Rlog.e(LOG_TAG, "fragmentText failed (" + pos + " >= " + nextPos + " or " +
                          nextPos + " >= " + textLen + ")");
                break;
            }
            result.add(text.substring(pos, nextPos));
            pos = nextPos;
        }
        return result;
    }

3、sendText()的实现如下:

public void sendTextMessage(
            String destinationAddress, String scAddress, String text,
            PendingIntent sentIntent, PendingIntent deliveryIntent) {
        if (TextUtils.isEmpty(destinationAddress)) {
            throw new IllegalArgumentException("Invalid destinationAddress");
        }

        if (TextUtils.isEmpty(text)) {
            throw new IllegalArgumentException("Invalid message body");
        }

        try {
            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
            if (iccISms != null) {
                iccISms.sendText(ActivityThread.currentPackageName(), destinationAddress,
                        scAddress, text, sentIntent, deliveryIntent);
            }
        } catch (RemoteException ex) {
            // ignore it
        }
    }
这里使用aidl的方式远程调用isms服务进行后续的发送流程,即

iccISms.sendText()


,IccSmsInterfaceManagerProxy的路径是frameworks/opt/telephony/src/java/com/android/internal/telephony/IccSmsInterfaceManagerProxy.java

关于isms服务的注册,它是在初始化phone进程时注册的

public IccSmsInterfaceManagerProxy(Context context,
            IccSmsInterfaceManager iccSmsInterfaceManager) {
        this.mContext = context;
        mIccSmsInterfaceManager = iccSmsInterfaceManager;
        if(ServiceManager.getService("isms") == null) {
            ServiceManager.addService("isms", this);
        }

        createWakelock();
    }

iccISms.sendSms()的实现如下:

@Override
    public void sendText(String callingPackage, String destAddr, String scAddr,
            String text, PendingIntent sentIntent, PendingIntent deliveryIntent) {
        mContext.enforceCallingPermission(
                android.Manifest.permission.SEND_SMS,
                "Sending SMS message");
        if (mIccSmsInterfaceManager.isShortSMSCode(destAddr)) {
            mIccSmsInterfaceManager.sendText(callingPackage, destAddr, scAddr, text,
                    sentIntent, deliveryIntent);
            return;
        }
        ArrayList<String> parts = new ArrayList<String>();
        parts.add(text);
        ArrayList<PendingIntent> sentIntents = new ArrayList<PendingIntent>();
        sentIntents.add(sentIntent);
        ArrayList<PendingIntent> deliveryIntents = new ArrayList<PendingIntent>();
        deliveryIntents.add(deliveryIntent);
        broadcastOutgoingSms(callingPackage, destAddr, scAddr, false, parts, sentIntents,
                deliveryIntents, -1);
    }
检查发送短信的APP是否有SEND_SMS权限,再调用broadcastOutgoingSms()

private void broadcastOutgoingSms(String callingPackage, String destAddr, String scAddr,
            boolean multipart, ArrayList<String> parts,
            ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents,
            int priority) {
        Intent broadcast = new Intent(Intent.ACTION_NEW_OUTGOING_SMS);
        broadcast.putExtra("destAddr", destAddr);
        broadcast.putExtra("scAddr", scAddr);
        broadcast.putExtra("multipart", multipart);
        broadcast.putExtra("callingPackage", callingPackage);
        broadcast.putExtra("callingUid", android.os.Binder.getCallingUid());
        broadcast.putStringArrayListExtra("parts", parts);
        broadcast.putParcelableArrayListExtra("sentIntents", sentIntents);
        broadcast.putParcelableArrayListExtra("deliveryIntents", deliveryIntents);
        broadcast.putExtra("priority", priority);
        mContext.sendOrderedBroadcastAsUser(broadcast, UserHandle.OWNER,
                android.Manifest.permission.INTERCEPT_SMS,
                mReceiver, null, Activity.RESULT_OK, destAddr, null);
    }

发送广播,Action为ACTION_NEW_OUTGOING_SMS,广播接收器就是参数中的mReceiver,mReceiver的定义如下:

private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            // check if the message was aborted
            if (getResultCode() != Activity.RESULT_OK) {
                return;
            }
            String destAddr = getResultData();
            String scAddr = intent.getStringExtra("scAddr");
            String callingPackage = intent.getStringExtra("callingPackage");
            ArrayList<String> parts = intent.getStringArrayListExtra("parts");
            ArrayList<PendingIntent> sentIntents =
                    intent.getParcelableArrayListExtra("sentIntents");
            ArrayList<PendingIntent> deliveryIntents =
                    intent.getParcelableArrayListExtra("deliveryIntents");

            if (intent.getIntExtra("callingUid", 0) != 0) {
                callingPackage = callingPackage + "\\" + intent.getIntExtra("callingUid", 0);
            }

            if (intent.getBooleanExtra("multipart", false)) {
                mIccSmsInterfaceManager.sendMultipartText(callingPackage, destAddr, scAddr,
                        parts, sentIntents, deliveryIntents);
                return;
            }

            PendingIntent sentIntent = null;
            if (sentIntents != null && sentIntents.size() > 0) {
                sentIntent = sentIntents.get(0);
            }
            PendingIntent deliveryIntent = null;
            if (deliveryIntents != null && deliveryIntents.size() > 0) {
                deliveryIntent = deliveryIntents.get(0);
            }
            String text = null;
            if (parts != null && parts.size() > 0) {
                text = parts.get(0);
            }
            mIccSmsInterfaceManager.sendText(callingPackage, destAddr, scAddr, text,
                    sentIntent, deliveryIntent);
        }
    };
这里调用mIccSmsInterfaceManager.sendText()继续发送流程

mIccSmsInterfaceManager对应的类是IccSmsInterfaceManager,路径是

framework/opt/telephony/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
mIccSmsInterfaceManager.sendText()的实现如下:

public void sendText(String callingPackage, String destAddr, String scAddr,
            String text, PendingIntent sentIntent, PendingIntent deliveryIntent) {
        int callingUid = Binder.getCallingUid();

        String[] callingParts = callingPackage.split("\\\\");
        if (callingUid == android.os.Process.PHONE_UID &&
                                         callingParts.length > 1) {
            callingUid = Integer.parseInt(callingParts[1]);
        }

        if (Binder.getCallingPid() != android.os.Process.myPid()) {
            mPhone.getContext().enforceCallingPermission(
                    Manifest.permission.SEND_SMS,
                    "Sending SMS message");
        }
        if (Rlog.isLoggable("SMS", Log.VERBOSE)) {
            log("sendText: destAddr=" + destAddr + " scAddr=" + scAddr +
                " text='"+ text + "' sentIntent=" +
                sentIntent + " deliveryIntent=" + deliveryIntent);
        }
        if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, callingUid,
                callingParts[0]) != AppOpsManager.MODE_ALLOWED) {
            return;
        }
        mDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent);
    }

这里调用mDispatcher.sendText()继续发送流程

mDispatcher对应的类是SmsDispatcher,源代码的路径是

framework/opt/telephony/src/java/com/android/internal/telephony/SMSDispatcher.java

SMSDispatcher是一个abstract类,继承它的子类有CdmaSMSDispatcher、GsmSMSDispatcher和IccSMSDispatcher,

这里的mDispatcher初始化如下:

protected IccSmsInterfaceManager(PhoneBase phone) {
        mPhone = phone;
        mContext = phone.getContext();
        mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
        mDispatcher = new ImsSMSDispatcher(phone,
                phone.mSmsStorageMonitor, phone.mSmsUsageMonitor);
    }

mDispatcher.sendText()是一个abstract方法,所以是在IccSMSDispatcher中实现,代码如下:

@Override
    protected void sendText(String destAddr, String scAddr, String text,
            PendingIntent sentIntent, PendingIntent deliveryIntent) {
        Rlog.d(TAG, "sendText");
        if (isCdmaMo()) {
            mCdmaDispatcher.sendText(destAddr, scAddr,
                    text, sentIntent, deliveryIntent);
        } else {
            mGsmDispatcher.sendText(destAddr, scAddr,
                    text, sentIntent, deliveryIntent);
        }
    }
这里根据sim卡的类型决定调用CdmaSMSDispatcher还是GsmSMSDispatcher,这里选择Gsm继续跟进。

mGsmDispatcher对应的类是GsmSMSDispatcher,源代码路径是

framework/opt/telephony/src/java/com/android/internal/telephony/GsmSMSDispatcher.java

mGsmDispatcher.sendText()的流程如下:

@Override
    protected void sendText(String destAddr, String scAddr, String text,
            PendingIntent sentIntent, PendingIntent deliveryIntent) {
        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
                scAddr, destAddr, text, (deliveryIntent != null));
        if (pdu != null) {
            HashMap map = getSmsTrackerMap(destAddr, scAddr, text, pdu);
            SmsTracker tracker = getSmsTracker(map, sentIntent, deliveryIntent,
                    getFormat());
            sendRawPdu(tracker);
        } else {
            Rlog.e(TAG, "GsmSMSDispatcher.sendText(): getSubmitPdu() returned null");
        }
    }

这里构造了SubmitPdu和SmsTracker对象,然后执行sendRawPdu(),这个方法是在父类SMSDiapatcher中实现的,代码如下:

    protected void sendRawPdu(SmsTracker tracker) {
	...

        // checkDestination() returns true if the destination is not a premium short code or the
        // sending app is approved to send to short codes. Otherwise, a message is sent to our
        // handler with the SmsTracker to request user confirmation before sending.
        if (checkDestination(tracker)) {
            // check for excessive outgoing SMS usage by this app
            if (!mUsageMonitor.check(appInfo.packageName, SINGLE_PART_SMS)) {
                sendMessage(obtainMessage(EVENT_SEND_LIMIT_REACHED_CONFIRMATION, tracker));
                return;
            }

            int ss = mPhone.getServiceState().getState();

            // if sms over IMS is not supported on data and voice is not available...
            if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) {
                handleNotInService(ss, tracker.mSentIntent);
            } else {
                sendSms(tracker);
            }
        }
    }
这里调用sendSms()继续发送流程,sendSms()是一个abstract方法,所以这里是在子类GsmSMSDispatcher中实现的,代码如下:

    @Override
    protected void sendSms(SmsTracker tracker) {
        HashMap<String, Object> map = tracker.mData;

        byte smsc[] = (byte[]) map.get("smsc");
        byte pdu[] = (byte[]) map.get("pdu");

        Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);

        if (tracker.mRetryCount > 0) {
            Rlog.d(TAG, "sendSms: "
                    + " mRetryCount=" + tracker.mRetryCount
                    + " mMessageRef=" + tracker.mMessageRef
                    + " SS=" + mPhone.getServiceState().getState());

            // per TS 23.040 Section 9.2.3.6:  If TP-MTI SMS-SUBMIT (0x01) type
            //   TP-RD (bit 2) is 1 for retry
            //   and TP-MR is set to previously failed sms TP-MR
            if (((0x01 & pdu[0]) == 0x01)) {
                pdu[0] |= 0x04; // TP-RD
                pdu[1] = (byte) tracker.mMessageRef; // TP-MR
            }
        }
        Rlog.d(TAG, "sendSms: "
                +" isIms()="+isIms()
                +" mRetryCount="+tracker.mRetryCount
                +" mImsRetry="+tracker.mImsRetry
                +" mMessageRef="+tracker.mMessageRef
                +" SS=" +mPhone.getServiceState().getState());

        // sms over gsm is used:
        //   if sms over IMS is not supported AND
        //   this is not a retry case after sms over IMS failed
        //     indicated by mImsRetry > 0
        if (0 == tracker.mImsRetry && !isIms()) {
            if (tracker.mRetryCount > 0) {
                // per TS 23.040 Section 9.2.3.6:  If TP-MTI SMS-SUBMIT (0x01) type
                //   TP-RD (bit 2) is 1 for retry
                //   and TP-MR is set to previously failed sms TP-MR
                if (((0x01 & pdu[0]) == 0x01)) {
                    pdu[0] |= 0x04; // TP-RD
                    pdu[1] = (byte) tracker.mMessageRef; // TP-MR
                }
            }
            mCi.sendSMS(IccUtils.bytesToHexString(smsc),
                    IccUtils.bytesToHexString(pdu), reply);
        } else {
            mCi.sendImsGsmSms(IccUtils.bytesToHexString(smsc),
                    IccUtils.bytesToHexString(pdu), tracker.mImsRetry,
                    tracker.mMessageRef, reply);
            // increment it here, so in case of SMS_FAIL_RETRY over IMS
            // next retry will be sent using IMS request again.
            tracker.mImsRetry++;
        }
    }

这里最终调用mCi.sendSms()继续发送流程,

mCi对应的类是CommandInterface,CommandInterface是一个Interface,RIL是它的一个子类,

也就是说短信发送在此处会调用RIL.java,执行sendText()方法,代码如下:

public void
    sendSMS (String smscPDU, String pdu, Message result) {
        RILRequest rr
                = RILRequest.obtain(RIL_REQUEST_SEND_SMS, result);

        constructGsmSendSmsRilRequest(rr, smscPDU, pdu);

        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));

        send(rr);
    }
程序交给send(RILRequest req)继续执行,代码如下:

protected void
    send(RILRequest rr) {
        Message msg;

        if (mSocket == null) {
            rr.onError(RADIO_NOT_AVAILABLE, null);
            rr.release();
            return;
        }

        msg = mSender.obtainMessage(EVENT_SEND, rr);

        acquireWakeLock();

        msg.sendToTarget();
    }
接下来RIL会将pdu等信息打包,通过socket发送给下层处理,最终形成at指令发送短信。

如果短信发送成功,还记得在发送时,从GsmSmsDispatcher.java传递到RIL.java中的Message吗,在发送之后,RIL.java会回调此Message,这个Message如下

Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
What = EVENT_SEND_SMS_COMPLETE,Object = tricker。SmsDispacher.java本身是一个Handler,所以这个Message最终在SmsDispacher.java中处理,处理逻辑代码如下:

@Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
        case EVENT_SEND_SMS_COMPLETE:
            // An outbound SMS has been successfully transferred, or failed.
            handleSendComplete((AsyncResult) msg.obj);
            break;
handleSendComplete的实现如下:

protected void handleSendComplete(AsyncResult ar) {
        SmsTracker tracker = (SmsTracker) ar.userObj;
        PendingIntent sentIntent = tracker.mSentIntent;

        if (ar.result != null) {
            tracker.mMessageRef = ((SmsResponse)ar.result).mMessageRef;
        } else {
            Rlog.d(TAG, "SmsResponse was null");
        }

        if (ar.exception == null) {
            if (DBG) Rlog.d(TAG, "SMS send complete. Broadcasting intent: " + sentIntent);

            if (SmsApplication.shouldWriteMessageForPackage(
                    tracker.mAppInfo.applicationInfo.packageName, mContext)) {
                // Persist it into the SMS database as a sent message
                // so the user can see it in their default app.
                tracker.writeSentMessage(mContext);
            }

            if (tracker.mDeliveryIntent != null) {
                // Expecting a status report.  Add it to the list.
                deliveryPendingList.add(tracker);
            }

            if (sentIntent != null) {
                try {
                    if (mRemainingMessages > -1) {
                        mRemainingMessages--;
                    }

                    if (mRemainingMessages == 0) {
                        Intent sendNext = new Intent();
                        sendNext.putExtra(SEND_NEXT_MSG_EXTRA, true);
                        sentIntent.send(mContext, Activity.RESULT_OK, sendNext);
                    } else {
                        sentIntent.send(Activity.RESULT_OK);
                    }
                } catch (CanceledException ex) {}
            }
        } else {
            if (DBG) Rlog.d(TAG, "SMS send failed");

            int ss = mPhone.getServiceState().getState();

            if ( tracker.mImsRetry > 0 && ss != ServiceState.STATE_IN_SERVICE) {
                // This is retry after failure over IMS but voice is not available.
                // Set retry to max allowed, so no retry is sent and
                //   cause RESULT_ERROR_GENERIC_FAILURE to be returned to app.
                tracker.mRetryCount = MAX_SEND_RETRIES;

                Rlog.d(TAG, "handleSendComplete: Skipping retry: "
                +" isIms()="+isIms()
                +" mRetryCount="+tracker.mRetryCount
                +" mImsRetry="+tracker.mImsRetry
                +" mMessageRef="+tracker.mMessageRef
                +" SS= "+mPhone.getServiceState().getState());
            }

            // if sms over IMS is not supported on data and voice is not available...
            if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) {
                handleNotInService(ss, tracker.mSentIntent);
            } else if ((((CommandException)(ar.exception)).getCommandError()
                    == CommandException.Error.SMS_FAIL_RETRY) &&
                   tracker.mRetryCount < MAX_SEND_RETRIES) {
                // Retry after a delay if needed.
                // TODO: According to TS 23.040, 9.2.3.6, we should resend
                //       with the same TP-MR as the failed message, and
                //       TP-RD set to 1.  However, we don't have a means of
                //       knowing the MR for the failed message (EF_SMSstatus
                //       may or may not have the MR corresponding to this
                //       message, depending on the failure).  Also, in some
                //       implementations this retry is handled by the baseband.
                tracker.mRetryCount++;
                Message retryMsg = obtainMessage(EVENT_SEND_RETRY, tracker);
                sendMessageDelayed(retryMsg, SEND_RETRY_DELAY);
            } else if (tracker.mSentIntent != null) {
                int error = RESULT_ERROR_GENERIC_FAILURE;

                if (((CommandException)(ar.exception)).getCommandError()
                        == CommandException.Error.FDN_CHECK_FAILURE) {
                    error = RESULT_ERROR_FDN_CHECK_FAILURE;
                }
                // Done retrying; return an error to the app.
                try {
                    Intent fillIn = new Intent();
                    if (ar.result != null) {
                        fillIn.putExtra("errorCode", ((SmsResponse)ar.result).mErrorCode);
                    }
                    if (mRemainingMessages > -1) {
                        mRemainingMessages--;
                    }

                    if (mRemainingMessages == 0) {
                        fillIn.putExtra(SEND_NEXT_MSG_EXTRA, true);
                    }

                    tracker.mSentIntent.send(mContext, error, fillIn);
                } catch (CanceledException ex) {}
            }
        }
    }
至此就是短信发送的在framework中的大体流程

首先检查AsyncResult对象中是否存在异常,如果成功发送的信息,那么不存在异常,如果发送失败,那么是存在Exception的,会进行异常的相应的逻辑处理,大体流程相似,故本处介绍无异常时的流程逻辑。

if (SmsApplication.shouldWriteMessageForPackage(
                    tracker.mAppInfo.applicationInfo.packageName, mContext)) {
                // Persist it into the SMS database as a sent message
                // so the user can see it in their default app.
                tracker.writeSentMessage(mContext);
            }
这里判断发送短信的app是否是默认短信,如果不是则保存该条短信到TelephonyProvider中。

最后会发送一个广播,这个广播的intent是PendingIntent,是在Mms中构造的,SmsReceiverService.java会接受该广播并处理
,比如保存短信的状态,失败或者发送成功

发送流程大概就是这样了。











  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值