隨筆篇1--短信模塊
很久沒有寫點(diǎn)技術(shù)筆記了财著,今天隨筆記錄和回憶一下之前短信模塊,以防被如今重復(fù)無(wú)積累的事情所遺忘撑碴。
正題 關(guān)于 GSM SMS && MMS 封裝篇
首先要理解一些基本的常見縮寫名詞
GSM Global System for MobileCommunication 全球移動(dòng)通信系統(tǒng)撑教,一種2G網(wǎng)絡(luò)標(biāo)準(zhǔn)
SMS Short Message Service 短消息服務(wù)
EMS Enhanced Message Service 增強(qiáng)型短消息服務(wù)
CBS Cell Broadcast Service 小區(qū)廣播服務(wù)
MMS Multimedia Message Service 多媒體消息服務(wù)
PDU Protocol Data Unit 協(xié)議數(shù)據(jù)單元,由Header和Data部分組成
TPDU Transfer Protocol Data Unit 傳輸協(xié)議數(shù)據(jù)單元醉拓,是傳輸層的PDU
MO Mobile Originated 消息的發(fā)送方
MT Mobile Terminal 消息的接收方
MS Mobile Station 移動(dòng)臺(tái)伟姐,在業(yè)務(wù)流程中可能是MO或者M(jìn)T
SMSC Short Message Service Centre 短消息服務(wù)中心
MMSC Multimedia Message Service Centre 多媒體消息服務(wù)中心
3GPP 3rd GenerationPartnership Project 第三代合作伙伴計(jì)劃,GSM核心的技術(shù)規(guī)范
OMA Open Mobile Alliance 開放移動(dòng)聯(lián)盟亿卤,一個(gè)標(biāo)準(zhǔn)化組織
RIL Radio Interface Layer 無(wú)線接口層愤兵,可以看做是modem的HAL層
SM-TL ShortMessage Transfer Layer 短消息傳輸過程中的傳輸層
OTA OverThe Air 空中接口
WAP Wireless Application Protocol 無(wú)線應(yīng)用協(xié)議,將HTML轉(zhuǎn)成WML以便傳輸
WSP Wireless Session Protocol 無(wú)線會(huì)話協(xié)議
SI Service Indication 服務(wù)通知排吴,讓用戶主動(dòng)打開的PUSH消息
SL Service Load 服務(wù)加載秆乳,PUSH消息到來(lái)會(huì)自動(dòng)打開鏈接
2.短信發(fā)送接口
短彩信的接口文件:frameworks\opt\telephony\src\java\android\telephony\SmsManager.java
? void sendTextMessage(
String destinationAddress, String scAddress, String text,
PendingIntent sentIntent, PendingIntent deliveryIntent);
? void sendTextMessage(String destinationAddress, String scAddress, String text,
PendingIntent sentIntent, PendingIntent deliveryIntent, int priority,
boolean isExpectMore, int validityPeriod);
? void sendMultimediaMessage(Context context, Uri contentUri, String locationUrl,
Bundle configOverrides, PendingIntent sentIntent);
.....還有很多不一一粘貼,可具體到類中查看
2 短消息類型
短消息服務(wù)分為:
普通短信:
單條短信最多160個(gè)7-BIT字符/140個(gè)8-BIT字符/70個(gè)16-BIT字符,多條普通短信將組成串接短信(SMS Concatenation)EMS:
Enhanced Message Service屹堰,歷史的產(chǎn)物肛冶,現(xiàn)在已經(jīng)見不到了,增強(qiáng)型短信双藕,可以發(fā)送少量的音頻淑趾,是多媒體彩信的前身,大小不能超過1KBCBS:
Cell Broadcast Service忧陪,小區(qū)廣播,國(guó)內(nèi)沒有這玩意
3 普通短信四種類型PDU
根據(jù)MTI(Message Type Indicator)類型可以將普通短信分成四種類型:SMS-SUBMIT近范,SMS-DELIVERY嘶摊,SMS-STATUS-REPORT,SMS-COMMAND评矩,其中SMS-COMMAND目前不支持叶堆。
3.1 First Byte
每個(gè)PDU的第一個(gè)字節(jié)包含了豐富的意義,
bit7: TP-Reply-Path
1 有
0 無(wú)
bit6: 指示是否有userdata header (UDH)
1 有
0 無(wú)
bit4.bit3: TP-Validity-Period (submit類型的PDU才有意義)
00: len=0
10: len=1
01/11: len=7
bit1.bit0: MTI – Message Type Indicator
00 Delevery (MT 短信:SC 》 MS)
01 Submit (MO短信:MS 》 SC)
10 Status Report (短信發(fā)送之后由SC反饋給發(fā)送方的狀態(tài)報(bào)告:SC 》 MS)
3.2 SMS-SUBMIT
MO類型短信斥杜,從MS 》 SMSC
解析方法在:
frameworks\opt\telephony\src\java\com\android\internal\telephony\gsm\ SmsMessage.java
void parseSmsSubmit(PduParser p, int firstByte)虱颗;
4 短信發(fā)送流程
短信發(fā)送需要destinationAddress(收件人號(hào)碼)、scAddress(短信中心蔗喂,可為null)忘渔、messages(消息內(nèi)容,是一個(gè)ArrayList缰儿,每條消息不能超出單條短信的長(zhǎng)度)畦粮、sentIntents(PendingIntent,短信發(fā)送到SMSC之后通知發(fā)送方)乖阵、deliveryIntents(PendingIntent宣赔,短信中心返回狀態(tài)報(bào)告之后通知發(fā)送方這條短信的狀態(tài))。
發(fā)送前需要構(gòu)造SMS-SUBMIT類型的PDU瞪浸。
4.2 GSM SmsMessage的解碼接口
frameworks\opt\telephony\src\java\com\android\internal\telephony\gsm\ SmsMessage.java提供了對(duì)短信內(nèi)容進(jìn)行編碼以及對(duì)短信PDU進(jìn)行解碼的操作儒将,這是GSM短信的最核心的內(nèi)容。
TextEncodingDetails calculateLength(CharSequence msgBody,
boolean use7bitOnly)对蒲;
2) SubmitPdu getSubmitPdu(String scAddress,
String destinationAddress, String message,
boolean statusReportRequested, byte[] header, int encoding,
int languageTable, int languageShiftTable, int validityPeriod)
3) SmsMessage newFromCMT(String[] lines)钩蚊;
4.3 計(jì)算長(zhǎng)度以確定編碼方式
最開始需要計(jì)算短信長(zhǎng)度,用以確定短信內(nèi)容的編碼方式齐蔽,調(diào)用的就是上面的接口calculateLength
-
7-BIT編碼規(guī)則在3GPP 23.038 clause 6.2中有詳細(xì)規(guī)定两疚,下面的這張表是GSM標(biāo)準(zhǔn)編碼表
QQ截圖hh.png
默認(rèn)的短信長(zhǎng)度是140個(gè)8-BIT字符,經(jīng)過7-BIT轉(zhuǎn)換之后得到 140 * 8 / 7 = 160個(gè)7-BIT字符
強(qiáng)制7bit 重要::這種需要在海外的項(xiàng)目中是有要求的含滴。因?yàn)橛行﹪?guó)外的運(yùn)營(yíng)商并沒有提供網(wǎng)絡(luò)側(cè)的轉(zhuǎn)換诱渤,比如德語(yǔ)?通常來(lái)說會(huì)要求轉(zhuǎn)成英文字母a,而這些一般是由運(yùn)營(yíng)商來(lái)做的谈况。
8-BIT勺美,這種編碼方式很少使用
16-BIT递胧,當(dāng)無(wú)法使用7-BIT進(jìn)行編碼時(shí),就會(huì)使用UCS2進(jìn)行編碼赡茸,這種編碼方式基本可以滿足我們的要求
4.4 構(gòu)造串接短信頭部
從應(yīng)用層傳過來(lái)的消息內(nèi)容條數(shù)可以知道這條短信是否是串接短信缎脾,如果是串接短信,需要構(gòu)造短信頭(SmsHeader占卧,即PDU中的UDH)來(lái)進(jìn)行組織遗菠。如下圖。
concatRef.refNumber標(biāo)識(shí)當(dāng)前的短信片段ID华蜒,這是從第一條短信片段開始逐一遞增的辙纬;
concatRef.seqNumber標(biāo)識(shí)這條短信片段在整條串接短信中的位置,這是用來(lái)標(biāo)識(shí)拼接順序的
concatRef.msgCount標(biāo)識(shí)這條串接短信的片段數(shù)
4.5 構(gòu)造PDU
有了足夠的元素叭喜,開始構(gòu)造SMS-SUBMIT PDU贺拣,還是調(diào)用SmsMessage中的getSubmitPdu方法。
1)構(gòu)造FisrtByte捂蕴,
2)填充UserData和UserDataLength
4.6 發(fā)送過程
SMS-SUBMIT 類型的PDU構(gòu)造完成譬涡,準(zhǔn)備調(diào)用RIL接口發(fā)送。
1)發(fā)送之前檢查當(dāng)時(shí)是否允許發(fā)送啥辨。
SmsUsageMonitor這個(gè)類是用來(lái)檢查某個(gè)APK短時(shí)間內(nèi)發(fā)送短信數(shù)量是否超標(biāo)涡匀。
有時(shí)候我們測(cè)試群發(fā)短信會(huì)彈出“在發(fā)送大量短信。是否允許該應(yīng)用繼續(xù)發(fā)送短信?”就是這個(gè)限制在起作用
2)RIL的處理方式是異步的委可,因此調(diào)用RIL接口發(fā)送之前悬荣,需要有Message來(lái)接收RIL的結(jié)果村怪。
。。宫补。凛剥。步淹。贾富。。崇决。材诽。。恒傻。脸侥。。盈厘。睁枕。。。外遇。注簿。未完待續(xù)