WAP PUSH解析(3)——Android中实现

田海立@CSDN

2012-06-30

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的封装格式。

这里总结一下:

  1. 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;
  2. 执行SmsDispatcher (具体实现类GsmSmsDispatcher /CdmaSmsDispatcher)的dispatchMessage()分发消息msg。有目标端口且目标端口是WAP PUSH(SmsHeader.PORT_WAP_PUSH)的信息,用WapPushOverSms::dispatchWapPdu()来处理;
  3. 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的处理,做如下实现:

  1. WapPushReceiver的onReceive()通过Intent的“data“参数,获取WBXML封装的PushData;
  2. 启动一个AsyncTask在后台解析WBXML封装的PushData,解析出PushData (XML格式);
  3. 解析XML格式的PushData,得到URL/Content/Signal等信息;
  4. 根据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标准,必看!

3.MIUI ROM接收WAP PUSH短信的补丁

Android上的WAPPUSH解析实现,有源代码,但是解析不全。

4.WAP Push over SMS

WAP PUSH over SMS的大致介绍(英文)

5.WAP Push SMS encoding

WAP PUSH Service Indication封装实例(英文)

6.Sending SMS WAPPush messages using the ActiveXperts SMSand MMS Toolkit

发送WAP PUSH的工具。是使用说明,虽然没实现细节,但可参考WBXML的Token和Attribute对照。(英文)

你可能感兴趣的:(android)