200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > Android短信发送流程之长短信发送(原)

Android短信发送流程之长短信发送(原)

时间:2022-07-04 01:39:45

相关推荐

Android短信发送流程之长短信发送(原)

从前面《Android短信发送流程之普通短信发送》流程看到,长短信与普通短信的流程从SmsManager的sendMultipartTextMessage()方法开始区分,现在我们来看长短信的流程:[java]view plaincopy@SmsManager.java publicvoidsendMultipartTextMessage(StringdestinationAddress,StringscAddress,ArrayList<String>parts,ArrayList<PendingIntent>sentIntents,ArrayList<PendingIntent>deliveryIntents){ if(TextUtils.isEmpty(destinationAddress)){ thrownewIllegalArgumentException("InvaliddestinationAddress"); } if(parts==null||parts.size()<1){ thrownewIllegalArgumentException("Invalidmessagebody"); } if(parts.size()>1){ //长短信发送 try{ ISmsiccISms=getISmsServiceOrThrow(); iccISms.sendMultipartText(ActivityThread.currentPackageName(), destinationAddress,scAddress,parts, sentIntents,deliveryIntents); }catch(RemoteExceptionex){ } }else{ //普通短信发送 PendingIntentsentIntent=null; PendingIntentdeliveryIntent=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()方法发送出去:[java]view plaincopy@UiccSmsController.java publicvoidsendMultipartText(StringcallingPackage,StringdestAddr,StringscAddr,List<String>parts,List<PendingIntent>sentIntents,List<PendingIntent>deliveryIntents)throwsandroid.os.RemoteException{ sendMultipartTextForSubscriber(getPreferredSmsSubscription(),callingPackage,destAddr,scAddr,parts,sentIntents,deliveryIntents); } publicvoidsendMultipartTextForSubscriber(longsubId,StringcallingPackage,StringdestAddr,StringscAddr,List<String>parts,List<PendingIntent>sentIntents,List<PendingIntent>deliveryIntents)throwsandroid.os.RemoteException{ IccSmsInterfaceManagericcSmsIntMgr=getIccSmsInterfaceManager(subId); if(iccSmsIntMgr!=null){ iccSmsIntMgr.sendMultipartText(callingPackage,destAddr,scAddr,parts,sentIntents, deliveryIntents); }else{ } }接下来UiccSmsController又把流程交给IccSmsInterfaceManager的sendMultipartText()来处理:[java]view plaincopy@IccSmsInterfaceManager.java publicvoidsendMultipartText(StringcallingPackage,StringdestAddr,StringscAddr,List<String>parts,List<PendingIntent>sentIntents,List<PendingIntent>deliveryIntents){ //权限检查 mPhone.getContext().enforceCallingPermission(Manifest.permission.SEND_SMS,"SendingSMSmessage"); if(mAppOps.noteOp(AppOpsManager.OP_SEND_SMS,Binder.getCallingUid(),callingPackage)!=AppOpsManager.MODE_ALLOWED){ return; } if(parts.size()>1&&parts.size()<10&&!SmsMessage.hasEmsSupport()){ //当前运营商不支持长短新,需要自行将短信分割后分别发送 for(inti=0;i<parts.size();i++){ //IfEMSisnotsupported,wehavetobreakdownEMSintosinglesegmentSMS //andaddpageinfo"x/y". StringsinglePart=parts.get(i); if(SmsMessage.shouldAppendPageNumberAsPrefix()){ singlePart=String.valueOf(i+1)+'/'+parts.size()+''+singlePart; }else{ singlePart=singlePart.concat(''+String.valueOf(i+1)+'/'+parts.size()); } PendingIntentsingleSentIntent=null; if(sentIntents!=null&&sentIntents.size()>i){ singleSentIntent=sentIntents.get(i); } PendingIntentsingleDeliveryIntent=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<String>)parts, (ArrayList<PendingIntent>)sentIntents,(ArrayList<PendingIntent>)deliveryIntents, null/*messageUri*/,callingPackage); }从上面来看,对于长短信,需要区分运营商是否支持的情况,如果不支持,需要我们将短信分割后逐条发送,如果支持,需要走不同流程,由于逐条发送时的流程与普通短信发送流程相同,因此这里主要分析以下运营商支持长短信的情况,也就时sendMultipartText()的流程:[java]view plaincopy@ImsSMSDispatcher.java protectedvoidsendMultipartText(StringdestAddr,StringscAddr, ArrayList<String>parts,ArrayList<PendingIntent>sentIntents, ArrayList<PendingIntent>deliveryIntents,UrimessageUri,StringcallingPkg){ 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中完成的:[java]view plaincopy@SMSDispatcher.java protectedvoidsendMultipartText(StringdestAddr,StringscAddr,ArrayList<String>parts,ArrayList<PendingIntent>sentIntents,ArrayList<PendingIntent>deliveryIntents,UrimessageUri,StringcallingPkg){ //将短信移入或写入发件箱 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); } intrefNumber=getNextConcatenatedRef()&0x00FF; intmsgCount=parts.size(); intencoding=SmsConstants.ENCODING_UNKNOWN; TextEncodingDetails[]encodingForParts=newTextEncodingDetails[msgCount]; for(inti=0;i<msgCount;i++){ TextEncodingDetailsdetails=calculateLength(parts.get(i),false); if(encoding!=details.codeUnitSize &&(encoding==SmsConstants.ENCODING_UNKNOWN ||encoding==SmsConstants.ENCODING_7BIT)){ encoding=details.codeUnitSize; } encodingForParts[i]=details; } //Statestotrackatthemessagelevel(forallparts) finalAtomicIntegerunsentPartCount=newAtomicInteger(msgCount); finalAtomicBooleananyPartFailed=newAtomicBoolean(false); for(inti=0;i<msgCount;i++){ SmsHeader.ConcatRefconcatRef=newSmsHeader.ConcatRef(); concatRef.refNumber=refNumber; concatRef.seqNumber=i+1;//1-basedsequence concatRef.msgCount=msgCount; //TODO:Wecurrentlysetthistotruesinceourmessagingappwillnever //sendmorethan255parts(itconvertsthemessagetoMMSwellbeforethat). //However,weshouldsupport3rdpartymessagingappsthatmightneed16-bit //references //Note:It'snotsufficienttojustflipthisbittotrue;itwillhave //rippleeffects(severalcalculationsassume8-bitref). concatRef.isEightBits=true; SmsHeadersmsHeader=newSmsHeader(); smsHeader.concatRef=concatRef; //Setthenationallanguagetablesfor3GPP7-bitencoding,ifenabled. if(encoding==SmsConstants.ENCODING_7BIT){ smsHeader.languageTable=encodingForParts[i].languageTable; smsHeader.languageShiftTable=encodingForParts[i].languageShiftTable; } PendingIntentsentIntent=null; if(sentIntents!=null&&sentIntents.size()>i){ sentIntent=sentIntents.get(i); } PendingIntentdeliveryIntent=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中实现的:[java]view plaincopyprotectedvoidsendNewSubmitPdu(StringdestinationAddress,StringscAddress,Stringmessage,SmsHeadersmsHeader,intencoding,PendingIntentsentIntent,PendingIntentdeliveryIntent,booleanlastPart,AtomicIntegerunsentPartCount,AtomicBooleananyPartFailed,UrimessageUri){ //对短信内容进行编码 SmsMessage.SubmitPdupdu=SmsMessage.getSubmitPdu(scAddress,destinationAddress, message,deliveryIntent!=null,SmsHeader.toByteArray(smsHeader), encoding,smsHeader.languageTable,smsHeader.languageShiftTable); if(pdu!=null){ HashMapmap=getSmsTrackerMap(destinationAddress,scAddress,message,pdu); //发送 SmsTrackertracker=getSmsTracker(map,sentIntent, deliveryIntent,getFormat(),unsentPartCount,anyPartFailed,messageUri, smsHeader,!lastPart); sendRawPdu(tracker); }else{ Rlog.e(TAG,"GsmSMSDispatcher.sendNewSubmitPdu():getSubmitPdu()returnednull"); } }接下来的流程和普通短信一样,最终通过RILJ将短信发送出去,并且注册回调消息为EVENT_SEND_SMS_COMPLETE。

也就是说,对于长短信而言,如果运营商不支持,那么就拆分为一个个普通短信然后逐条发送,如果运营商支持长短信,则会对每个分组短信添加SmsHeader的信息头,然后逐条发送。

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

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

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

Source:/u010961631/article/details/50272729

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。