从前面《 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. 清单文件,测试,打电话和发短信应用
  4. 【Android休眠】之Android对PowerKey事件的处理(1)代码流程
  5. Android(安卓)利用发送Intent播放本地视频和网络视频
  6. Android(安卓)Telechips89xx背光控制流程
  7. Android实现发送短信功能实例详解
  8. Android热插拔事件处理流程
  9. Android发送数据到web服务器4种方式

随机推荐

  1. androidのemail学习
  2. Android String类型转换为float、double
  3. Android网格布局的简单使用
  4. Android(安卓)访问 Tomcat SSL双向验证服
  5. Android常见小问题汇总
  6. Android studio 3.2.0 使用Android Devic
  7. Android recovery 工作原理
  8. Android中TextView内容过长加省略号,设置
  9. [原]如何在Android平台上建立APN
  10. Android数字证书具体应用机制