从前面《 Android短信发送流程之普通短信发送》流程看到,长短信与普通短信的流程从SmsManager的sendMultipartTextMessage()方法开始区分,现在我们来看长短信的流程:
        @SmsManager.java        public void sendMultipartTextMessage( String destinationAddress, String scAddress, ArrayList parts, ArrayList sentIntents, ArrayList 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 = getISmsServiceOrThrow();                    iccISms.sendMultipartText(ActivityThread.currentPackageName(),                            destinationAddress, scAddress, parts,                            sentIntents, deliveryIntents);                } catch (RemoteException ex) {                }            } 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);            }        }
        在上面的方法中,对于长短信将会通过iccISms对象也就是UiccSmsController的sendMultipartText()方法发送出去:
        @UiccSmsController.java        public void sendMultipartText(String callingPackage, String destAddr, String scAddr, List parts, List sentIntents, List deliveryIntents) throws android.os.RemoteException {            sendMultipartTextForSubscriber(getPreferredSmsSubscription(), callingPackage, destAddr, scAddr, parts, sentIntents, deliveryIntents);        }        public void sendMultipartTextForSubscriber(long subId, String callingPackage, String destAddr, String scAddr, List parts, List sentIntents, List deliveryIntents) throws android.os.RemoteException {            IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);            if (iccSmsIntMgr != null ) {                iccSmsIntMgr.sendMultipartText(callingPackage, destAddr, scAddr, parts, sentIntents,                        deliveryIntents);            } else {            }        }
        接下来UiccSmsController又把流程交给IccSmsInterfaceManager的sendMultipartText()来处理:
        @IccSmsInterfaceManager.java        public void sendMultipartText(String callingPackage, String destAddr, String scAddr, List parts, List sentIntents, List deliveryIntents) {            //权限检查            mPhone.getContext().enforceCallingPermission( Manifest.permission.SEND_SMS, "Sending SMS message");            if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(), callingPackage) != AppOpsManager.MODE_ALLOWED) {                return;            }            if (parts.size() > 1 && parts.size() < 10 && !SmsMessage.hasEmsSupport()) {                //当前运营商不支持长短新,需要自行将短信分割后分别发送                for (int i = 0; i < parts.size(); i++) {                    // If EMS is not supported, we have to break down EMS into single segment SMS                    // and add page info " x/y".                    String singlePart = parts.get(i);                    if (SmsMessage.shouldAppendPageNumberAsPrefix()) {                        singlePart = String.valueOf(i + 1) + '/' + parts.size() + ' ' + singlePart;                    } else {                        singlePart = singlePart.concat(' ' + String.valueOf(i + 1) + '/' + parts.size());                    }                    PendingIntent singleSentIntent = null;                    if (sentIntents != null && sentIntents.size() > i) {                        singleSentIntent = sentIntents.get(i);                    }                    PendingIntent singleDeliveryIntent = null;                    if (deliveryIntents != null && deliveryIntents.size() > i) {                        singleDeliveryIntent = deliveryIntents.get(i);                    }                    //将长短信分割,挨个发送                    mDispatcher.sendText(destAddr, scAddr, singlePart,                            singleSentIntent, singleDeliveryIntent,                            null/*messageUri*/, callingPackage);                }                return;            }            //运营商支持长短信,直接发送即可            mDispatcher.sendMultipartText(destAddr, scAddr, (ArrayList) parts,                    (ArrayList) sentIntents, (ArrayList) deliveryIntents,                    null/*messageUri*/, callingPackage);        }
        从上面来看,对于长短信, 需要区分运营商是否支持的情况,如果不支持,需要我们将短信分割后逐条发送,如果支持,需要走不同流程,由于逐条发送时的流程与普通短信发送流程相同,因此这里主要分析以下运营商支持长短信的情况,也就时sendMultipartText()的流程:
        @ImsSMSDispatcher.java        protected void sendMultipartText(String destAddr, String scAddr,                ArrayList parts, ArrayList sentIntents,                ArrayList deliveryIntents, Uri messageUri, String callingPkg) {            if (isCdmaMo()) {                //CDMA                mCdmaDispatcher.sendMultipartText(destAddr, scAddr,                        parts, sentIntents, deliveryIntents, messageUri, callingPkg);            } else {                //GSM                mGsmDispatcher.sendMultipartText(destAddr, scAddr,                        parts, sentIntents, deliveryIntents, messageUri, callingPkg);            }        }
        和普通短信类似,也许要区分当前的网络环境,对于GSM来说,就是使用GsmSMSDispatcher来继续处理,这个处理是在GsmSMSDispatcher父类SMSDispatcher中完成的:
        @SMSDispatcher.java        protected void sendMultipartText(String destAddr, String scAddr, ArrayList parts, ArrayList sentIntents, ArrayList deliveryIntents, Uri messageUri, String callingPkg) {            //将短信移入或写入发件箱            if (messageUri == null) {                if (SmsApplication.shouldWriteMessageForPackage(callingPkg, mContext)) {                    messageUri = writeOutboxMessage(                            getSubId(),                            destAddr,                            getMultipartMessageText(parts),                            deliveryIntents != null && deliveryIntents.size() > 0,                            callingPkg);                }            } else {                moveToOutbox(getSubId(), messageUri, callingPkg);            }            int refNumber = getNextConcatenatedRef() & 0x00FF;            int msgCount = parts.size();            int encoding = SmsConstants.ENCODING_UNKNOWN;            TextEncodingDetails[] encodingForParts = new TextEncodingDetails[msgCount];            for (int i = 0; i < msgCount; i++) {                TextEncodingDetails details = calculateLength(parts.get(i), false);                if (encoding != details.codeUnitSize                        && (encoding == SmsConstants.ENCODING_UNKNOWN                            || encoding == SmsConstants.ENCODING_7BIT)) {                    encoding = details.codeUnitSize;                            }                encodingForParts[i] = details;            }            // States to track at the message level (for all parts)            final AtomicInteger unsentPartCount = new AtomicInteger(msgCount);            final AtomicBoolean anyPartFailed = new AtomicBoolean(false);            for (int i = 0; i < msgCount; i++) {                SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();                concatRef.refNumber = refNumber;                concatRef.seqNumber = i + 1;  // 1-based sequence                concatRef.msgCount = msgCount;                // TODO: We currently set this to true since our messaging app will never                // send more than 255 parts (it converts the message to MMS well before that).                // However, we should support 3rd party messaging apps that might need 16-bit                // references                // Note:  It's not sufficient to just flip this bit to true; it will have                // ripple effects (several calculations assume 8-bit ref).                concatRef.isEightBits = true;                SmsHeader smsHeader = new SmsHeader();                smsHeader.concatRef = concatRef;                // Set the national language tables for 3GPP 7-bit encoding, if enabled.                if (encoding == SmsConstants.ENCODING_7BIT) {                    smsHeader.languageTable = encodingForParts[i].languageTable;                    smsHeader.languageShiftTable = encodingForParts[i].languageShiftTable;                }                PendingIntent sentIntent = null;                if (sentIntents != null && sentIntents.size() > i) {                    sentIntent = sentIntents.get(i);                }                PendingIntent deliveryIntent = null;                if (deliveryIntents != null && deliveryIntents.size() > i) {                    deliveryIntent = deliveryIntents.get(i);                }                //逐条发送                sendNewSubmitPdu(destAddr, scAddr, parts.get(i), smsHeader, encoding,                        sentIntent, deliveryIntent, (i == (msgCount - 1)),                        unsentPartCount, anyPartFailed, messageUri);            }        }
        在上面的过程中我们看到,对于运营商支持的长短信情况, 需要把拆分出来的短信分别加上短信头编码,也就是SmsHeader,然后分别调用sendNewSubmitPdu()方法进行发送。
        这里需要简单介绍以下SmsHeader作用, 普通的短信中SmsHeader为空,所以只有长短信才会有该数据。他内部确定了该长短信分组的大小、每个分组的索引、编码格式等信息。
        接下来看sendNewSubmitPdu()的过程,这个方法是在GsmSMSDispatcher中实现的:
        protected void sendNewSubmitPdu(String destinationAddress, String scAddress, String message, SmsHeader smsHeader, int encoding, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart, AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri) {            //对短信内容进行编码            SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(scAddress, destinationAddress,                    message, deliveryIntent != null, SmsHeader.toByteArray(smsHeader),                    encoding, smsHeader.languageTable, smsHeader.languageShiftTable);            if (pdu != null) {                HashMap map =  getSmsTrackerMap(destinationAddress, scAddress, message, pdu);                //发送                SmsTracker tracker = getSmsTracker(map, sentIntent,                        deliveryIntent, getFormat(), unsentPartCount, anyPartFailed, messageUri,                        smsHeader, !lastPart);                sendRawPdu(tracker);            } else {                Rlog.e(TAG, "GsmSMSDispatcher.sendNewSubmitPdu(): getSubmitPdu() returned null");            }        }
        接下来的流程和普通短信一样,最终通过RILJ将短信发送出去,并且注册回调消息为EVENT_SEND_SMS_COMPLETE。
        也就是说, 对于长短信而言,如果运营商不支持,那么就拆分为一个个普通短信然后逐条发送,如果运营商支持长短信,则会对每个分组短信添加SmsHeader的信息头,然后逐条发送。

        所以当SMSDispatcher接收到EVENT_SEND_SMS_COMPLETE消息时,就说明,无论是普通短信或者长短信,都已经发送完毕。

        以上就是长短信的发送流程。

        多收件人的情况,请见下节介绍。

更多相关文章

  1. Android中打电话的数据流程
  2. Android实现发送短信功能实例详解
  3. Android Telechips89xx背光控制流程
  4. 【Android休眠】之Android对PowerKey事件的处理(1)代码流程
  5. Android热插拔事件处理流程
  6. Android framework 源码分析一Activity启动流程(android 8.0)
  7. android重启流程
  8. Android4.4 Activity启动流程
  9. android开机动画启动流程

随机推荐

  1. [Android(安卓)Pro] Android应用性能测试
  2. [Android进阶]Android消息机制
  3. Android中使用到的四种类型的PNG图片
  4. App测试中ios和Android的区别
  5. android 中webview基本使用的方法小结
  6. Android使用NFC模拟M卡实现 (三)
  7. Android(安卓)Service生命周期及用法
  8. android学习计划
  9. android base64转pdf文件的展示
  10. android改进布局性能