原文:http://blog.csdn.net/thl789/article/details/7705494
Android中已经实现了SMS PDU的解析、WSP的解析,得到了WBXML封装的数据,并发出了广播"android.provider.Telephony.WAP_PUSH_RECEIVED"。原生实现中还没有对mimeType类型为WAP PUSH SI 和WAP PUSH SL 的该广播的响应,亦即,缺少对WBXML封装的PUSH数据的处理。本文通过分析总结Android中的原生实现,给出WAP PUSH SI/SL的实现参考。
一、Android中的原生实现
笔者已经有几篇文章分别描述SMS的接收处理过程,SMS PDU / WSP / WBXML的封装格式。
- 《Android中的SMS接收处理》侧重于SMS接收处理过程的描述;
- 《WAP PUSH解析(1)——SMS PDU编码》侧重于描述PDU的封装格式;
- 《WAP PUSH解析(2)——WSP以及WBXML编码》描述WSP和WBXML的封装。
这里总结一下:
- RIL中收到new SMS,调用android.telephony.SmsMessage.newFromCMT() decode PDU,结果放入SmsMessage中。android.telephony.SmsMessage.newFromCMT() 根据电话的类型,用com.android.internal.telephony.gsm.SmsMessage或com.android.internal.telephony.cdma.SmsMessage的newFromCMT()真正的实现PDU decode;
- 执行SmsDispatcher (具体实现类GsmSmsDispatcher /CdmaSmsDispatcher)的dispatchMessage()分发消息msg。有目标端口且目标端口是WAP PUSH(SmsHeader.PORT_WAP_PUSH)的信息,用WapPushOverSms::dispatchWapPdu()来处理;
- WapPushOverSms::dispatchWapPdu()中解析WSP,得到对应ContentType的MIME Type:Service Indication (SI)为"application/vnd.wap.sic";Service Load (SL)为"application/vnd.wap.slc"。对SI和SL类型,调用dispatchWapPdu_default()。
下面是dispatchWapPdu_default()的实现:
- private void dispatchWapPdu_default(byte[]pdu, int transactionId, int pduType,
- StringmimeType, int headerStartIndex, int headerLength) {
- byte[] header = new byte[headerLength];
- System.arraycopy(pdu, headerStartIndex,header, 0, header.length);
- int dataIndex = headerStartIndex +headerLength;
- byte[] data;
- data = new byte[pdu.length -dataIndex];
- System.arraycopy(pdu, dataIndex, data,0, data.length);
- Intent intent = newIntent(Intents.WAP_PUSH_RECEIVED_ACTION);
- intent.setType(mimeType);
- intent.putExtra("transactionId", transactionId);
- intent.putExtra("pduType",pduType);
- intent.putExtra("header",header);
- intent.putExtra("data",data);
- mSmsDispatcher.dispatch(intent,"android.permission.RECEIVE_WAP_PUSH");
- }
以上都是在Framework中处理的,可以看到Framework中已经解析出了SI/SL的WBXML封装的数据,并通过Broadcast广播出去了。接下来,对mimeType标识的具体业务的处理,是application层的工作。而对mimeType为"application/vnd.wap.sic"(SI)和"application/vnd.wap.slc"(SL)的WAP_PUSH_RECEIVED的处理,Android的原生实现中没有实现。
关注一下发出广播的Intent参数:
- mimeType: “application/vnd.wap.sic"或 application/vnd.wap.slc";
- header: WSP解析出来的header,用来识别ContentType的,已经有了mimeType,这个已经没什么意义;
- data: WBXML封装的SI或SL XML数据。
要实现完整的WAP PUSH,只要:
- 实现mimeType为"application/vnd.wap.sic"(SI)和"application/vnd.wap.slc"(SL)的WAP_PUSH_RECEIVED的处理;
- 收到的广播中实现对WBXML封装的SI/SL解析,并插入消息库。
可参考MMS中对"application/vnd.wap.mms-message"(MMS)类型的WAP_PUSH_RECEIVED处理的实现。
二、处理"android.provider.Telephony.WAP_PUSH_RECEIVED"
要处理"android.provider.Telephony.WAP_PUSH_RECEIVED",定义BroardcastReceiver实现类WapPushReceiver,并在AndroidManifest.xml中加入对"application/vnd.wap.sic"(SI)和"application/vnd.wap.slc"(SL)类型的WAP_PUSH_RECEIVED处理的声明。
- <receiver android:name=".transaction.WapPushReceiver"
- android:permission="android.permission.BROADCAST_WAP_PUSH">
- <intent-filter>
- <action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
- <data android:mimeType="application/vnd.wap.sic" />
- <data android:mimeType="application/vnd.wap.slc" />
- </intent-filter>
- </receiver>
三、WapPushReceiver中对WBXML解析
可参考原生实现中MMS中PushReceiver的处理,做如下实现:
- WapPushReceiver的onReceive()通过Intent的“data“参数,获取WBXML封装的PushData;
- 启动一个AsyncTask在后台解析WBXML封装的PushData,解析出PushData (XML格式);
- 解析XML格式的PushData,得到URL/Content/Signal等信息;
- 根据3的结果,选择加入Message数据库,并通知用户。
这里面关键点是WBXML格式的解析,可以参考 MIUI ROM接收WAP PUSH短信的补丁。这是为小米手机做的WAP PUSH解析实现,里面有WBXML解析的源代码可参考。不过这里面对WBXML中定义的TAG和Attribute的支持不全,读者可根据自己需求加入所需要的支持。
参考资料
1. Google Android source2.3.7_r1
Android原生实现源代码
2. WAP Binary XMLContent Format
WBXML标准,必看!
Android上的WAPPUSH解析实现,有源代码,但是解析不全。
WAP PUSH over SMS的大致介绍(英文)
WAP PUSH Service Indication封装实例(英文)
6. Sending SMS WAPPush messages using the ActiveXperts SMSand MMS Toolkit
发送WAP PUSH的工具。是使用说明,虽然没实现细节,但可参考WBXML的Token和Attribute对照。(英文)