Android短信发送流程之长短信发送(原)
生活随笔
收集整理的這篇文章主要介紹了
Android短信发送流程之长短信发送(原)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
?從前面《
Android短信發(fā)送流程之普通短信發(fā)送
》流程看到,長短信與普通短信的流程從SmsManager的sendMultipartTextMessage()方法開始區(qū)分,現(xiàn)在我們來看長短信的流程:
[java]?view plaincopy @SmsManager.java?? 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)?{?? ????????//長短信發(fā)送?? ????????try?{?? ????????????ISms?iccISms?=?getISmsServiceOrThrow();?? ????????????iccISms.sendMultipartText(ActivityThread.currentPackageName(),?? ????????????????????destinationAddress,?scAddress,?parts,?? ????????????????????sentIntents,?deliveryIntents);?? ????????}?catch?(RemoteException?ex)?{?? ????????}?? ????}?else?{?? ????????//普通短信發(fā)送?? ????????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);?? ????}?? }??
? ? ? ? 在上面的方法中,對(duì)于長短信將會(huì)通過iccISms對(duì)象也就是UiccSmsController的sendMultipartText()方法發(fā)送出去:
[java]?view plaincopy @UiccSmsController.java?? public?void?sendMultipartText(String?callingPackage,?String?destAddr,?String?scAddr,?List<String>?parts,?List<PendingIntent>?sentIntents,?List<PendingIntent>?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<String>?parts,?List<PendingIntent>?sentIntents,?List<PendingIntent>?deliveryIntents)?throws?android.os.RemoteException?{?? ????IccSmsInterfaceManager?iccSmsIntMgr?=?getIccSmsInterfaceManager(subId);?? ????if?(iccSmsIntMgr?!=?null?)?{?? ????????iccSmsIntMgr.sendMultipartText(callingPackage,?destAddr,?scAddr,?parts,?sentIntents,?? ????????????????deliveryIntents);?? ????}?else?{?? ????}?? }??
? ? ? ? 接下來UiccSmsController又把流程交給IccSmsInterfaceManager的sendMultipartText()來處理:
[java]?view plaincopy @IccSmsInterfaceManager.java?? public?void?sendMultipartText(String?callingPackage,?String?destAddr,?String?scAddr,?List<String>?parts,?List<PendingIntent>?sentIntents,?List<PendingIntent>?deliveryIntents)?{?? ????//權(quán)限檢查?? ????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())?{?? ????????//當(dāng)前運(yùn)營商不支持長短新,需要自行將短信分割后分別發(fā)送?? ????????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);?? ????????????}?? ?? ?? ????????????//將長短信分割,挨個(gè)發(fā)送?? ????????????mDispatcher.sendText(destAddr,?scAddr,?singlePart,?? ????????????????????singleSentIntent,?singleDeliveryIntent,?? ????????????????????null/*messageUri*/,?callingPackage);?? ????????}?? ????????return;?? ????}?? ????//運(yùn)營商支持長短信,直接發(fā)送即可?? ????mDispatcher.sendMultipartText(destAddr,?scAddr,?(ArrayList<String>)?parts,?? ????????????(ArrayList<PendingIntent>)?sentIntents,?(ArrayList<PendingIntent>)?deliveryIntents,?? ????????????null/*messageUri*/,?callingPackage);?? }??
? ? ? ? 從上面來看,對(duì)于長短信,
需要區(qū)分運(yùn)營商是否支持的情況
,如果不支持,需要我們將短信分割后逐條發(fā)送,如果支持,需要走不同流程,由于逐條發(fā)送時(shí)的流程與普通短信發(fā)送流程相同,因此這里主要分析以下運(yùn)營商支持長短信的情況,也就時(shí)sendMultipartText()的流程:
[java]?view plaincopy @ImsSMSDispatcher.java?? protected?void?sendMultipartText(String?destAddr,?String?scAddr,?? ????????ArrayList<String>?parts,?ArrayList<PendingIntent>?sentIntents,?? ????????ArrayList<PendingIntent>?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);?? ????}?? }??
? ? ? ? 和普通短信類似,也許要區(qū)分當(dāng)前的網(wǎng)絡(luò)環(huán)境,對(duì)于GSM來說,就是使用GsmSMSDispatcher來繼續(xù)處理,這個(gè)處理是在GsmSMSDispatcher父類SMSDispatcher中完成的:
[java]?view plaincopy @SMSDispatcher.java?? protected?void?sendMultipartText(String?destAddr,?String?scAddr,?ArrayList<String>?parts,?ArrayList<PendingIntent>?sentIntents,?ArrayList<PendingIntent>?deliveryIntents,?Uri?messageUri,?String?callingPkg)?{?? ????//將短信移入或?qū)懭氚l(fā)件箱?? ????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);?? ????????}?? ?? ?? ????????//逐條發(fā)送?? ????????sendNewSubmitPdu(destAddr,?scAddr,?parts.get(i),?smsHeader,?encoding,?? ????????????????sentIntent,?deliveryIntent,?(i?==?(msgCount?-?1)),?? ????????????????unsentPartCount,?anyPartFailed,?messageUri);?? ????}?? }??
? ? ? ? 在上面的過程中我們看到,對(duì)于運(yùn)營商支持的長短信情況,
需要把拆分出來的短信分別加上短信頭編碼
,也就是SmsHeader,然后分別調(diào)用sendNewSubmitPdu()方法進(jìn)行發(fā)送。
? ? ? ? 這里需要簡單介紹以下SmsHeader作用, 普通的短信中SmsHeader為空,所以只有長短信才會(huì)有該數(shù)據(jù) 。他內(nèi)部確定了該長短信分組的大小、每個(gè)分組的索引、編碼格式等信息。
? ? ? ? 接下來看sendNewSubmitPdu()的過程,這個(gè)方法是在GsmSMSDispatcher中實(shí)現(xiàn)的: [java]?view plaincopy 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)?{?? ????//對(duì)短信內(nèi)容進(jìn)行編碼?? ????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);?? ????????//發(fā)送?? ????????SmsTracker?tracker?=?getSmsTracker(map,?sentIntent,?? ????????????????deliveryIntent,?getFormat(),?unsentPartCount,?anyPartFailed,?messageUri,?? ????????????????smsHeader,?!lastPart);?? ????????sendRawPdu(tracker);?? ????}?else?{?? ????????Rlog.e(TAG,?"GsmSMSDispatcher.sendNewSubmitPdu():?getSubmitPdu()?returned?null");?? ????}?? }??
? ? ? ? 接下來的流程和普通短信一樣,最終通過RILJ將短信發(fā)送出去,并且注冊(cè)回調(diào)消息為EVENT_SEND_SMS_COMPLETE。
? ? ? ? 也就是說, 對(duì)于長短信而言,如果運(yùn)營商不支持,那么就拆分為一個(gè)個(gè)普通短信然后逐條發(fā)送,如果運(yùn)營商支持長短信,則會(huì)對(duì)每個(gè)分組短信添加SmsHeader的信息頭,然后逐條發(fā)送。
? ? ? ? 這里需要簡單介紹以下SmsHeader作用, 普通的短信中SmsHeader為空,所以只有長短信才會(huì)有該數(shù)據(jù) 。他內(nèi)部確定了該長短信分組的大小、每個(gè)分組的索引、編碼格式等信息。
? ? ? ? 接下來看sendNewSubmitPdu()的過程,這個(gè)方法是在GsmSMSDispatcher中實(shí)現(xiàn)的: [java]?view plaincopy
? ? ? ? 也就是說, 對(duì)于長短信而言,如果運(yùn)營商不支持,那么就拆分為一個(gè)個(gè)普通短信然后逐條發(fā)送,如果運(yùn)營商支持長短信,則會(huì)對(duì)每個(gè)分組短信添加SmsHeader的信息頭,然后逐條發(fā)送。
? ? ? ? 所以當(dāng)SMSDispatcher接收到EVENT_SEND_SMS_COMPLETE消息時(shí),就說明,無論是普通短信或者長短信,都已經(jīng)發(fā)送完畢。
? ? ? ? 以上就是長短信的發(fā)送流程。
? ? ? ??多收件人的情況,請(qǐng)見下節(jié)介紹。
Source:?http://blog.csdn.net/u010961631/article/details/50272729
與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的Android短信发送流程之长短信发送(原)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android短信发送流程之普通短信发送
- 下一篇: Android短信发送流程之多收件人发送