android 彩信,android 彩信接收到附件的下载原理分析

转:http://xiaoyuang.com/print.php?id=12586

首先,了解下彩信收发的宏观步骤:

a、 终端A向彩信中心(MMSC)发送一条彩信,通过WAP网关POST到MMSC

b、 MMSC通过PushProxy网关,向SMSC(短信中心)发送PUSH消息,SMSC转发到终端B

c、 终端B通过WAP网关利用GET方法从MMSC获取一条彩信

d、 MMSC通过PushProxy网关和SNSC向终端A发送一条传送报告(delivery report)

从上面这个步骤可以看出,彩信的接收分两个步骤:

1、接收到短信。

2、分析短信然后通过http来获取彩信附件。

因此彩信第一步跟短信的接收流程一样,在RILReceiver

接收到短信转到processUnsolicited进行处理。

GSM 方式(最近才知道短信的收发有两种,一种就是通过GSM,另一种是通过CDMA):

GSM其事件类型为

RIL_UNSOL_RESPONSE_NEW_SMS。先调用responseString从Parcel中获取数据,再使用

newFromCMT方法获取SmsMessage对象,最后调用mSMSRegistrant的notifyRegistrant方法设置消息类型

(what属性为EVENT_NEW_SMS)并转到SMSDispatcher进行处理。这个时候就会调用子类(GsmSMSDispatcher)的

dispatchMessage方法处理。

protected int dispatchMessage(SmsMessageBase smsb) {

// If sms is

null, means there was a parsing error.

if (smsb == null) {

return Intents.RESULT_SMS_GENERIC_ERROR;

}

SmsMessage sms = (SmsMessage) smsb;

boolean handled = false;

if (sms.isTypeZero()) {

// As per 3GPP TS 23.040 9.2.3.9, Type Zero messages should not

be

// Displayed/Stored/Notified. They should only be

acknowledged.

Log.d(TAG, "Received short message type 0, Dont display or store

it. Send Ack");

return Intents.RESULT_SMS_HANDLED;

}

// Special case the message waiting indicator messages

if (sms.isMWISetMessage()) {

mGsmPhone.updateMessageWaitingIndicator(true);

handled = sms.isMwiDontStore();

if (Config.LOGD) {

Log.d(TAG, "Received voice mail indicator set SMS shouldStore=" +

!handled);

}

} else if (sms.isMWIClearMessage()) {

mGsmPhone.updateMessageWaitingIndicator(false);

handled = sms.isMwiDontStore();

if (Config.LOGD) {

Log.d(TAG, "Received voice mail indicator clear SMS shouldStore=" +

!handled);

}

}

if (handled) {

return Intents.RESULT_SMS_HANDLED;

}

if (!mStorageAvailable &&

(sms.getMessageClass() != MessageClass.CLASS_0)) {

// Its a storable message and theres no storage available.

Bail.

// (See TS 23.038 for a description of class 0 messages.)

return Intents.RESULT_SMS_OUT_OF_MEMORY;

}

SmsHeader smsHeader = sms.getUserDataHeader();

// See if message is partial or port addressed.

if ((smsHeader == null) || (smsHeader.concatRef == null)) {

// Message is not partial (not part of concatenated

sequence).

byte[][] pdus = new byte[1][];

pdus[0] = sms.getPdu();

if (smsHeader != null &&

smsHeader.portAddrs != null) {

if (smsHeader.portAddrs.destPort == SmsHeader.PORT_WAP_PUSH)

{

return mWapPush.dispatchWapPdu(sms.getUserData());

} else {

// The message was sent to a port, so concoct a URI for it.

dispatchPortAddressedPdus(pdus,

smsHeader.portAddrs.destPort);

}

} else {

// Normal short and non-port-addressed message, dispatch it.

dispatchPdus(pdus);

}

return Activity.RESULT_OK;

} else {

// Process the message part.

return processMessagePart(sms, smsHeader.concatRef,

smsHeader.portAddrs);

}

}

在这个方法里,将会判断接收到的短信是否长短信、是否彩信、是否普通短信。

首先获取SmsHeader,

如果SmsHeader或SmsHeader.concatRef均不为空,说明是长短信,则调用processMessagePart将短信分段存入

raw表,待所有分段都收到后,将其组装。然后根据端口的不同,按照彩信通知(WapPushOverSms的dispatchWapPdu方法)、指定端口的彩信(dispatchPortAddressedPdus)、长短信(dispatchPdus)进行分发处理。

a4c26d1e5885305701be709a3d33442f.png

继续分析彩信,如果是彩信就调用WapPushOverSms类dispatchWapPdu的方法。(该类的位置)

a4c26d1e5885305701be709a3d33442f.png

public int

dispatchWapPdu(byte[] pdu) {

if (Config.LOGD) Log.d(LOG_TAG, "Rx: " +

IccUtils.bytesToHexString(pdu));

int index = 0;

int transactionId = pdu[index++] &

0xFF;

int pduType = pdu[index++] & 0xFF;

int headerLength = 0;

if ((pduType != WspTypeDecoder.PDU_TYPE_PUSH)

&&

(pduType != WspTypeDecoder.PDU_TYPE_CONFIRMED_PUSH)) {

if (Config.LOGD) Log.w(LOG_TAG, "Received non-PUSH WAP PDU. Type =

" + pduType);

return Intents.RESULT_SMS_HANDLED;

}

pduDecoder = new WspTypeDecoder(pdu);

if (pduDecoder.decodeUintvarInteger(index) == false) {

if (Config.LOGD) Log.w(LOG_TAG, "Received PDU. Header Length

error.");

return Intents.RESULT_SMS_GENERIC_ERROR;

}

headerLength = (int)pduDecoder.getValue32();

index += pduDecoder.getDecodedDataLength();

int headerStartIndex = index;

if (pduDecoder.decodeContentType(index) == false) {

if (Config.LOGD) Log.w(LOG_TAG, "Received PDU. Header Content-Type

error.");

return Intents.RESULT_SMS_GENERIC_ERROR;

}

int binaryContentType;

String mimeType = pduDecoder.getValueString();

if (mimeType == null) {

binaryContentType = (int)pduDecoder.getValue32();

// TODO we should have more generic way to map binaryContentType

code to mimeType.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值