- 浏览: 355870 次
- 性别:
- 来自: 南京
文章分类
最新评论
-
nglxl:
点赞啊,必须点赞!!深度好文,解决了困扰我多年的疑惑。
tcp 长连接与短连接 -
cofftech:
opengl源码http://www.eyesourcecod ...
OPenGL ES 关键API小结 -
mail_j:
不是很好用,很多情况都不能处理 1、没有区分关键字的大小写2、 ...
Java解析sql语句,分析出调用到的所有表 -
a455642158:
就算监听到变成了cmwap还不行,还得监听网络连接状态Stat ...
android APN切换cmwap实现 -
xuhl1022:
看了您的android 4篇 浏览器二次开发,感触颇深,写的很 ...
Android浏览器Browser二次开发(四)浏览器中的APN切换
1 WAP PUSH 流程简介
WAP Push分为两种:SI(Service Initiate) 和SL(Service Load)。都是服务器端向客户端推送消息的一种方式。
先看SI:
‘图发不上来’
图1.1
服务器通过网关采用OTA协议把信息发送到手机,手机存储解析并存储信息,然后提示给用户。
而SL流程如下:
‘图发不上来’
图1.2
在接收到SL消息后,同样也会存储并提示用户(视情况具体对待),区别在于客户端会主动调用浏览器打开SL中附带的连接。
2 WAP PUSH消息体剖析
下面我们以SL为例,来看看WAP PUSH的消息。
一个SL的WAP PUSH消息主体大致如下:
<!--
Service Loading (SL) Document Type Definition.
SL is an XML language. Typical usage:
<?xml version="1.0"?>
<!DOCTYPE sl PUBLIC "-//WAPFORUM//DTD SL 1.0//EN"
"http://www.wapforum.org/DTD/sl.dtd">
<sl>
href %URI; #REQUIRED
action (execute-low|execute-high|cache) "execute-low"
</sl>
大家都看到了,其实内容很少,包括一个连接和一个action控制执行的优先级。
由于考虑到节约网络数据的传输,往往都是将这些文本转化为WBXML格式再进行传输。WBXML是一种压缩的二进制表示方式,有严格的定义。对于标签和属性,定义如下表:
Tag Name Token
sl 5
Attribute Name Attribute Value Prefix Token
action execute-low 5
action execute-high 6
action cache 7
href 8
href http:// 9
href http://www. A
href https:// B
href https://www. C
Attribute Value Token
.com/ 85
.edu/ 86
.net/ 87
.org/ 88
文本中的对应Tag和Attribute value会被Token代替,以减少文本大小。我们看下面一段内容:
<?xml version="1.0"?>
<!DOCTYPE sl PUBLIC "-//WAPFORUM//DTD SL 1.0//EN"
"http://www.wapforum.org/DTD/sl.dtd">
<sl href="http://www.xyz.com/ppaid/123/abc.wml"></sl>
总共有159个字节。
我们使用WBXML格式来表示,如下表对应关系:
Token Stream Description
02 Version number - WBXML version 1.2
06 SL 1.0 Public Identifier
6A Charset=UTF-8 (MIBEnum 106)
00 String table length
05 sl, with attributes
0A Token for "href="http://www."
03 Inline string follows
‘x’, ‘y’, ‘z’, 00 String
85 Token for ".com/"
03 Inline string follows
‘p’, ‘p’, ‘a’, ‘i’, ‘d’, ‘/’, ‘1’, ‘2’, ‘3’, ‘/’, ‘a’, ‘b’, ‘c’, ‘.’, ‘w’, ‘m’, ‘l’, 00 String
01 END (of sl attribute list)
这样一来,就是:
02 06 6A 00 05 0A 03 'x' 'y' 'z' 00 85 03 'p' 'p' 'a'
'i' 'd' '/' '1' '2' '3' '/' 'a' 'b' 'c' '.' 'w' 'm' 'l' 00 01
总共才需要32个字节, 大大减少了数据量。
以上的只是消息主体内容,在传输过来的时候,还需要加上一些附加的信息,如
mimeType: 表示是SI还是SL, application/vnd.wap.sic或者 application/vnd.wap.slc (text/vnd.wap.sl).
transactionId: 用于分段发送大数据量的消息, 这些消息具有相同的trasactionId.
pduType: 未识别
header: 附加信息,用于标示特定的业务。
3 Android中解析WAP PUSH
按照以上所述,网络传输过来的是WBXML数据,通常我们需要按照Token表对应的进行解析,才可以得到XML格式的正文,从而获取href和action。 庆幸的是Android中在framework层的WapPushOverSms.java中已经完成了对消息的部分解析,把mimeType, trasactionId, pduType, header 和 data分离出来,放在intent的传递参数中了。看以下代码:
private void dispatchWapPdu_PushCO(byte[] pdu, int transactionId, int pduType,
int headerStartIndex, int headerLength) {
byte[] header = new byte[headerLength];
System.arraycopy(pdu, headerStartIndex, header, 0, header.length);
Intent intent = new Intent(Intents.WAP_PUSH_RECEIVED_ACTION);
intent.setType(WspTypeDecoder.CONTENT_MIME_TYPE_B_PUSH_CO);
intent.putExtra("transactionId", transactionId);
intent.putExtra("pduType", pduType);
intent.putExtra("header", header);
intent.putExtra("data", pdu);
mSmsDispatcher.dispatch(intent, "android.permission.RECEIVE_WAP_PUSH");
}
我们在应用层只需要添加对WAP_PUSH_RECEIVED_ACTION的监听,便可获取到这个WAP PUSH。 下面以接收中国移动DCD业务的WAP PUSH为例,看看是如何实现的。
需要写一个DcdWapPushReceiver.java:
public class DcdWapPushReceiver extends BroadcastReceiver {
private static final String LOGTAG = "DcdPushReceiver";
public static final String CONTENT_MIME_TYPE_B_PUSH_SL = "application/vnd.wap.slc";
public static final String APPLICATION_DCD_ID = "application/x-oma-DCD:DCD.ua";
public void onReceive(Context context, Intent intent) {
//only deal with SL WAP PUSH
if (intent.getAction().equals(WAP_PUSH_RECEIVED_ACTION)
&& CONTENT_MIME_TYPE_B_PUSH_SL.equals(intent.getType())) {
// Start a new AsyncTask to process the data.
if (APPLICATION_DCD_ID.equals(getAppIdFromIntent(intent))) {
new ReceivePushTask(context).execute(intent);
}
}
}
/*
* get application id from intent header.
* <==header sample==>
* B0 B4 87 AF application/x-oma-DCD:DCD.ua 00 Encoding-Version 00
*/
public static String getAppIdFromIntent(Intent intent) {
byte[] header = intent.getByteArrayExtra("header");
if (header == null) {
return null;
}
String str = new String(header);
int start = str.indexOf("application/");
if (start > 0) {
//application id end with 00.
int end = str.indexOf(0x00);
if (end > 0) {
str = str.substring(start, end);
return str;
}
}
return null;
}
private class ReceivePushTask extends AsyncTask<Intent, Void, Void> {
private Context mContext;
public ReceivePushTask(Context context) {
mContext = context;
}
protected Void doInBackground(Intent... intents)
{
Intent intent = intents[0];
// step1. obtain wbxml data from intent.
byte[] pushData = intent.getByteArrayExtra("data");
String wbxmlData = "";
for (byte by: pushData) {
wbxmlData = wbxmlData + by + " ";
}
Debug.print("wap push data = "+wbxmlData);
// step2. pass the data to WapPushParser and get the parsing result.
DcdWapPushParser parser = new DcdWapPushParser(pushData);
DcdWapPushMsg pushMsg = null;
if (CONTENT_MIME_TYPE_B_PUSH_SL.equals(intent.getType())) {
pushMsg = parser.parse(DcdWapPushMsg.WAP_PUSH_TYPE_SL);
}
if (null == pushMsg) {
Debug.error("Invalid WAP PUSH data");
return null;
}
//get href
String href = pushMsg.getAttributeValueString(DcdWapPushMsg.WAP_PUSH_PROJECTION_HREF);
Debug.print("href = " + href);
Intent i = new Intent(mContext, DcdCmService.class);
//step3. sync invoked by wap push, so set sync type to SVR
//i.putExtra("syncType", DcdCmService.SYNC_TYPE_SVR);
//i.putExtra("href", href);
Bundle bundle = new Bundle();
bundle.putBoolean(DcdCmService.NOTIFICATION_WAPPUSH, true);
bundle.putString("syncType", DcdRequest.REQUEST_TYPE_SVR);
bundle.putString("href", href);
i.putExtras(bundle);
//start sync service
mContext.startService(i);
return null;
}
}
}
在AndroidManifest.xml中注册这个接收器:
<receiver android:name=".contentmanager.DcdWapPushReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
<data android:mimeType="application/vnd.wap.slc" />
</intent-filter>
</receiver>
WAP Push分为两种:SI(Service Initiate) 和SL(Service Load)。都是服务器端向客户端推送消息的一种方式。
先看SI:
‘图发不上来’
图1.1
服务器通过网关采用OTA协议把信息发送到手机,手机存储解析并存储信息,然后提示给用户。
而SL流程如下:
‘图发不上来’
图1.2
在接收到SL消息后,同样也会存储并提示用户(视情况具体对待),区别在于客户端会主动调用浏览器打开SL中附带的连接。
2 WAP PUSH消息体剖析
下面我们以SL为例,来看看WAP PUSH的消息。
一个SL的WAP PUSH消息主体大致如下:
<!--
Service Loading (SL) Document Type Definition.
SL is an XML language. Typical usage:
<?xml version="1.0"?>
<!DOCTYPE sl PUBLIC "-//WAPFORUM//DTD SL 1.0//EN"
"http://www.wapforum.org/DTD/sl.dtd">
<sl>
href %URI; #REQUIRED
action (execute-low|execute-high|cache) "execute-low"
</sl>
大家都看到了,其实内容很少,包括一个连接和一个action控制执行的优先级。
由于考虑到节约网络数据的传输,往往都是将这些文本转化为WBXML格式再进行传输。WBXML是一种压缩的二进制表示方式,有严格的定义。对于标签和属性,定义如下表:
Tag Name Token
sl 5
Attribute Name Attribute Value Prefix Token
action execute-low 5
action execute-high 6
action cache 7
href 8
href http:// 9
href http://www. A
href https:// B
href https://www. C
Attribute Value Token
.com/ 85
.edu/ 86
.net/ 87
.org/ 88
文本中的对应Tag和Attribute value会被Token代替,以减少文本大小。我们看下面一段内容:
<?xml version="1.0"?>
<!DOCTYPE sl PUBLIC "-//WAPFORUM//DTD SL 1.0//EN"
"http://www.wapforum.org/DTD/sl.dtd">
<sl href="http://www.xyz.com/ppaid/123/abc.wml"></sl>
总共有159个字节。
我们使用WBXML格式来表示,如下表对应关系:
Token Stream Description
02 Version number - WBXML version 1.2
06 SL 1.0 Public Identifier
6A Charset=UTF-8 (MIBEnum 106)
00 String table length
05 sl, with attributes
0A Token for "href="http://www."
03 Inline string follows
‘x’, ‘y’, ‘z’, 00 String
85 Token for ".com/"
03 Inline string follows
‘p’, ‘p’, ‘a’, ‘i’, ‘d’, ‘/’, ‘1’, ‘2’, ‘3’, ‘/’, ‘a’, ‘b’, ‘c’, ‘.’, ‘w’, ‘m’, ‘l’, 00 String
01 END (of sl attribute list)
这样一来,就是:
02 06 6A 00 05 0A 03 'x' 'y' 'z' 00 85 03 'p' 'p' 'a'
'i' 'd' '/' '1' '2' '3' '/' 'a' 'b' 'c' '.' 'w' 'm' 'l' 00 01
总共才需要32个字节, 大大减少了数据量。
以上的只是消息主体内容,在传输过来的时候,还需要加上一些附加的信息,如
mimeType: 表示是SI还是SL, application/vnd.wap.sic或者 application/vnd.wap.slc (text/vnd.wap.sl).
transactionId: 用于分段发送大数据量的消息, 这些消息具有相同的trasactionId.
pduType: 未识别
header: 附加信息,用于标示特定的业务。
3 Android中解析WAP PUSH
按照以上所述,网络传输过来的是WBXML数据,通常我们需要按照Token表对应的进行解析,才可以得到XML格式的正文,从而获取href和action。 庆幸的是Android中在framework层的WapPushOverSms.java中已经完成了对消息的部分解析,把mimeType, trasactionId, pduType, header 和 data分离出来,放在intent的传递参数中了。看以下代码:
private void dispatchWapPdu_PushCO(byte[] pdu, int transactionId, int pduType,
int headerStartIndex, int headerLength) {
byte[] header = new byte[headerLength];
System.arraycopy(pdu, headerStartIndex, header, 0, header.length);
Intent intent = new Intent(Intents.WAP_PUSH_RECEIVED_ACTION);
intent.setType(WspTypeDecoder.CONTENT_MIME_TYPE_B_PUSH_CO);
intent.putExtra("transactionId", transactionId);
intent.putExtra("pduType", pduType);
intent.putExtra("header", header);
intent.putExtra("data", pdu);
mSmsDispatcher.dispatch(intent, "android.permission.RECEIVE_WAP_PUSH");
}
我们在应用层只需要添加对WAP_PUSH_RECEIVED_ACTION的监听,便可获取到这个WAP PUSH。 下面以接收中国移动DCD业务的WAP PUSH为例,看看是如何实现的。
需要写一个DcdWapPushReceiver.java:
public class DcdWapPushReceiver extends BroadcastReceiver {
private static final String LOGTAG = "DcdPushReceiver";
public static final String CONTENT_MIME_TYPE_B_PUSH_SL = "application/vnd.wap.slc";
public static final String APPLICATION_DCD_ID = "application/x-oma-DCD:DCD.ua";
public void onReceive(Context context, Intent intent) {
//only deal with SL WAP PUSH
if (intent.getAction().equals(WAP_PUSH_RECEIVED_ACTION)
&& CONTENT_MIME_TYPE_B_PUSH_SL.equals(intent.getType())) {
// Start a new AsyncTask to process the data.
if (APPLICATION_DCD_ID.equals(getAppIdFromIntent(intent))) {
new ReceivePushTask(context).execute(intent);
}
}
}
/*
* get application id from intent header.
* <==header sample==>
* B0 B4 87 AF application/x-oma-DCD:DCD.ua 00 Encoding-Version 00
*/
public static String getAppIdFromIntent(Intent intent) {
byte[] header = intent.getByteArrayExtra("header");
if (header == null) {
return null;
}
String str = new String(header);
int start = str.indexOf("application/");
if (start > 0) {
//application id end with 00.
int end = str.indexOf(0x00);
if (end > 0) {
str = str.substring(start, end);
return str;
}
}
return null;
}
private class ReceivePushTask extends AsyncTask<Intent, Void, Void> {
private Context mContext;
public ReceivePushTask(Context context) {
mContext = context;
}
protected Void doInBackground(Intent... intents)
{
Intent intent = intents[0];
// step1. obtain wbxml data from intent.
byte[] pushData = intent.getByteArrayExtra("data");
String wbxmlData = "";
for (byte by: pushData) {
wbxmlData = wbxmlData + by + " ";
}
Debug.print("wap push data = "+wbxmlData);
// step2. pass the data to WapPushParser and get the parsing result.
DcdWapPushParser parser = new DcdWapPushParser(pushData);
DcdWapPushMsg pushMsg = null;
if (CONTENT_MIME_TYPE_B_PUSH_SL.equals(intent.getType())) {
pushMsg = parser.parse(DcdWapPushMsg.WAP_PUSH_TYPE_SL);
}
if (null == pushMsg) {
Debug.error("Invalid WAP PUSH data");
return null;
}
//get href
String href = pushMsg.getAttributeValueString(DcdWapPushMsg.WAP_PUSH_PROJECTION_HREF);
Debug.print("href = " + href);
Intent i = new Intent(mContext, DcdCmService.class);
//step3. sync invoked by wap push, so set sync type to SVR
//i.putExtra("syncType", DcdCmService.SYNC_TYPE_SVR);
//i.putExtra("href", href);
Bundle bundle = new Bundle();
bundle.putBoolean(DcdCmService.NOTIFICATION_WAPPUSH, true);
bundle.putString("syncType", DcdRequest.REQUEST_TYPE_SVR);
bundle.putString("href", href);
i.putExtras(bundle);
//start sync service
mContext.startService(i);
return null;
}
}
}
在AndroidManifest.xml中注册这个接收器:
<receiver android:name=".contentmanager.DcdWapPushReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
<data android:mimeType="application/vnd.wap.slc" />
</intent-filter>
</receiver>
- RAR.rar (13 KB)
- 下载次数: 146
评论
4 楼
cigogo
2012-04-20
多谢博主的无私分享,写的很好!
3 楼
jianweizhang_3
2011-08-09
附件的文件是 不全 能发份全的吗?
2 楼
jianweizhang_3
2011-08-09
附件的文件什么不全啊
1 楼
wswb
2011-07-08
介绍得不错,不过附件的代码不是很全
发表评论
-
基于Java NIO的手机答题游戏开发
2014-03-31 17:59 1702先上个游戏截图: 豌豆荚地址: http://apps.w ... -
enable android deviceconnection under linux
2013-04-24 15:45 957开发环境搭建完毕,Eclipse,Java,ADT都已经折腾 ... -
set CCache for building android source code
2013-04-24 15:14 1147Setting up ccache You can opti ... -
android 源码下载403 forbidden, 406 not acceptable 错误
2013-04-24 08:46 2410解决方法 1. 浏览器登录https://android.g ... -
ubuntu11.10 编译android4.0 错处
2013-04-08 21:45 1183今天使用ubuntu11.10编译android4.0出现以下 ... -
常用WebService列表
2013-01-31 23:22 2598快递查询接口 http://webservice.36wu.c ... -
startActivityForResult 无响应问题
2013-01-24 13:57 3712今天开发遇到了个问题, 就是从一个Activity中使用sta ... -
Android中仿新浪微博刷新列表
2012-11-22 17:35 7307大家看到新浪微博中的列表往下拉的时候, 头部出现正在刷新,然后 ... -
Grid调整间距
2012-09-29 08:52 1678今天使用GridView, 发现点中某一Item时选中部分的背 ... -
android gallery和Animation组合使用, 看美女美图
2012-09-11 21:01 4330今天主要探究Gallery和Animation的使用。 制作一 ... -
Android执行 shell command
2012-03-24 17:00 7210Android执行shell命令 一、方法 1. /* ... -
BBBBBB111
2012-03-23 11:42 10陈波: 本周:代码review,解决findbugs中bug以 ... -
MonkeyTestError
2012-03-21 10:15 903-20 21:36:42.439 W/dalvikvm( ... -
INSTALL_FAILED_OLDER_SDK ERROR
2012-03-12 15:52 4385Install APK with adb: $ platfo ... -
4.0源码编译问题
2012-03-07 17:12 31161、fatal error: GL/glx.h: No suc ... -
4.0 编译apk中无classes.dex
2012-03-07 17:11 3894下载完android 4.0代码,模拟器里面的gallery不 ... -
Android 4.0源码编译错误
2012-03-05 10:19 2536UNEXPECTED TOP-LEVEL EXCEPTION: ... -
AndroidLockScreenDemo
2012-02-18 15:54 919锁屏解锁的成功案例。 -
G14 root权限获取
2012-02-13 23:36 2818HTC G14 ROOT权限获取后就能删除系统自带的程序,相信 ... -
锁屏d ds
2011-12-15 00:49 832private final IDevicePolicyMana ...
相关推荐
因此,WAP PUSH实现了短信和WAP业务的结合,节省了您寻找业务的时间,方便您直接找到并使用自己喜 欢的业务。PUSH信息无论是否被用户打开,都会保留在手机 的"推入收件箱"内,用户可以重复打开。 wap push 的意思...
但是针对不同的手机厂家的android系统(略有不同),有的拦截就不成功了。 一般情况下,使用较标准的Google的android系统,拦截比较成功(例如:摩托罗拉)。 如果手机厂商做了较大的改动,拦截可能会有问题。 例如...
本文档是个人在android2.2、2.3平台添加Wap push总结文档,已成功实现了此功能。请不要随便转载,
android 开发 push 短信协议解析,push短信头,sl,si,co三种push短信的协议解析。用来支持android中mms不支持push短信的缺陷。开发必备
android.permission.BROADCAST_WAP_PUSH,WAP PUSH服务收到后触发一个广播 拨打电话 android.permission.CALL_PHONE,允许程序从非系统拨号器里输入电话号码 通话权限 android.permission.CALL_PRIVILEGED,...
支持 HTTP 、 WAP Push 和 xHTML ;支持 POP 、 IMAP 、 SMTP ,以及 AOL 和 GMAIL 电子邮件服务;支持 AIM 、 MSN 、雅虎通和 GTALK ;与谷歌日历同步;与 Android Market 联机;支持谷歌 “ 街景 ” 服务;包装盒...
本.txt文档中记录了自身从事Android 移动开发中遇到的SMS PDU编解码问题的点点滴滴,其中记录了3gpp和3gpp2短信pdu的解码构成,通过对短信PDU编解码更加熟悉完成了业务功能需求,对从事android telephony业务的新手...
拦截器 用于静默短信检测的 Android 调试区 简单的 android logcat 监视器,用于检查唯一的低... Silent Wap Push Tested on a rooted Sony Xperia J Model ST26i Android 4.1.2 Kernel Version 3.4.0 user@sibldsr