对于移动终端,有时候服务器返回的是WML格式的页面。 比如说中国移动的一些需要使用cmwap接入点的业务页面(DCD, 移动梦网…), 这就要求终端浏览器必须能够支持对WML格式页面的解析和显示。 Android原始代码里的webkit层虽然提供了WML相关的解析类,但是并没有很好地支持,所以在页面上无法正确显示。 我们需要做以下一些修改:
1. 打开对WML格式解析的通道
修改源码的\external\webkit\WebCore\dom\DOMImplementation.cpp
获取到服务器返回的数据中的content-type字段值后,会调用这个类里面的isXMLMIMEType()方法来判断是否按照XML格式来解析。我们看这个方法:
1
2
3
4
5
6
7
|
bool DOMImplementation::isXMLMIMEType( const
String& mimeType) {
if
(mimeType == "text/xml"
|| mimeType == "application/xml"
|| mimeType == "text/xsl" )
return
true ;
static
const char *
const validChars =
"[0-9a-zA-Z_\\-+~!$\\^{}|.%'`#&*]" ;
DEFINE_STATIC_LOCAL(RegularExpression, xmlTypeRegExp, (String( "^" ) + validChars +
"+/" + validChars +
"+\\+xml$" , TextCaseSensitive));
return
xmlTypeRegExp.match(mimeType) > - 1 ;
}
|
这里只包含了text/xml, application/xml, text/xls. 我们需要把WML相应的MiMeType类型加进去
1
|
If(mimeType == “text/vnd.wap.wml”)
return true ;
|
修改framework/base/core/java/android/webkit/LoadListener.java, 源码如下:
1
2
3
4
5
6
7
8
9
|
private
void handleHeaders(Headers headers) {
…
}
else
if (mMimeType.equals( "text/vnd.wap.wml" )) {
mMimeType =
"text/plain" ;
}
|
我们可以看到, 原来是不支持wml格式的, 都当做text/plain来处理了,这样显然是不能正确显示的。 所以这一行mMimeType = "text/plain";需要注释掉,打开给外围。
2. 对WML中的超链接元素(WMLAElement和WMLAnchorElement)中href属性值里面的变量替换。
笔者发现,在一个WML的登陆页面上,填入用户名和密码后,点击登陆,附加到url后面的用户名和密码是$(username) 和$(password) ,有web开发经验的XDJM都知道,这是没有将变量替换为页面上相应值。我们看WMLAElement.cpp中处理点击事件的方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
void
WMLAElement::defaultEventHandler(Event* event) {
if
(isLink() && (event->type() == eventNames().clickEvent || (event->type() == eventNames().keydownEvent && focused()))) {
MouseEvent* e =
0 ;
if
(event->type() == eventNames().clickEvent && event->isMouseEvent())
e = static_cast<MouseEvent*>(event);
KeyboardEvent* k =
0 ;
if
(event->type() == eventNames().keydownEvent && event->isKeyboardEvent())
k = static_cast<KeyboardEvent*>(event);
if
(e && e->button() == RightButton) {
WMLElement::defaultEventHandler(event);
return ;
}
if
(k) {
if
(k->keyIdentifier() != "Enter" ) {
WMLElement::defaultEventHandler(event);
return ;
}
event->setDefaultHandled();
dispatchSimulatedClick(event);
return ;
}
if
(!event->defaultPrevented() && document()->frame()) {
String url = document()->completeURL(deprecatedParseURL(getAttribute(HTMLNames::hrefAttr)));
/
document()->frame()->loader()->urlSelected(url, target(), event,
false , false ,
true , SendReferrer);
}
event->setDefaultHandled();
}
}
|
通过打印Log发现,getAttribute(HTMLNames::hrefAttr)获取的只是href后面的字符串,包含变量$(). 我们需要对其中的变量进行转化。还好WMLVariables里面已经提供了相应的方法substituteVariableReferences,不需要我们再去写一个了。修改如下
#include "WMLVariables.h"
1
2
3
4
5
6
|
if
(!event->defaultPrevented() && document()->frame()) {
href = substituteVariableReferences(href, document(), WMLVariableEscapingEscape);
String url = document()->completeURL(deprecatedParseURL(href));
document()->frame()->loader()->urlSelected(url, target(), event,
false , false ,
true , SendReferrer);
}
|
别忘了,WMLAnchorElement.cpp中相应的地方也要同样改掉。
3. 在页面上长按链接时弹出选项点击失效
这是由于点击时是从webkit层去获取这个链接的地址和标题的, 而源码中只考虑了HTML格式的页面, WML页面被忽略了。 返回的href为null.
首先要在WMLAElement.cpp中提供接口, 返回链接。
1
2
3
4
5
6
|
KURL WMLAElement::href()
const {
String href = substituteVariableReferences(getAttribute(HTMLNames::hrefAttr),
document(), WMLVariableEscapingEscape);
return
document()->completeURL(href);
}
|
由于WMLAnchorElement继承了WMLAElement, 就不需要再添加这个方法了。
然后修改WebViewCore.cpp, 原来获取href的方法是这样的:
1
2
3
4
|
WebCore::String WebViewCore::retrieveHref(WebCore::Frame* frame, WebCore::Node* node) {
WebCore::HTMLAnchorElement* anchor = retrieveAnchorElement(frame, node);
return
anchor ? anchor->href() : WebCore::String();
}
|
在这里增加WML的支持, 修改如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/**add WML anchor support. 20110224, begin**/
# if
ENABLE(WML)
WebCore::WMLAnchorElement* WebViewCore::retrieveWMLAElement(WebCore::Frame* frame, WebCore::Node* node) {
if
(!CacheBuilder::validNode(m_mainFrame, frame, node))
return
0 ;
if
(!node->hasTagName(WebCore::WMLNames::aTag))
return
0 ;
return
static_cast<WebCore::WMLAnchorElement*>(node);
}
#endif
/**add WML anchor support 20110224, end**/
WebCore::String WebViewCore::retrieveHref(WebCore::Frame* frame, WebCore::Node* node) {
/**retrieve WMLAnchor element. 20110224, begin**/
# if
ENABLE(WML)
if
(node->isWMLElement()) {
WebCore::WMLAnchorElement* anchor = retrieveWMLAElement(frame, node);
return
anchor ? anchor->href() : WebCore::String();
}
#endif
/**retrieve WMLAnchor element. 20110224, end**/
WebCore::HTMLAnchorElement* anchor = retrieveAnchorElement(frame, node);
return
anchor ? anchor->href() : WebCore::String();
}
|
还有获取链接标题的方法,修改如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
WebCore::String WebViewCore::retrieveAnchorText(WebCore::Frame* frame, WebCore::Node* node) {
/**retrieve WMLAnchor element. 20110224, begin**/
# if
ENABLE(WML)
if
(node->isWMLElement()) {
WebCore::WMLAnchorElement* anchor = retrieveWMLAElement(frame, node);
return
anchor ? anchor->title() : WebCore::String();
}
#endif
/**retrieve WMLAnchor element. 20110224, end**/
WebCore::HTMLAnchorElement* anchor = retrieveAnchorElement(frame, node);
return
anchor ? anchor->text() : WebCore::String();
}
|
4. 移动梦网无法正确显示,解析出错。
移动梦网返回的数据格式为application/vnd.wap.xhtml+xml, 包含了xhtml和xml两种格式。而CMCC的数据本身又不是严格按照W3C标准来的, 导致在解析的时候出现了语法错误提示。 对于这种情况,我们显然无法去要求CMCC改变数据, 只能把这种格式当做普通的html来显示, html没有那么严格的语法检查, 可以正常显示。修改framework/base/core/java/android/webkit/LoadListener.java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
private
void handleHeaders(Headers headers) {
。。。
String contentType = headers.getContentType();
if
(contentType != null ) {
parseContentTypeHeader(contentType);
if
(mMimeType.equals( "text/plain" ) ||
mMimeType.equals( "application/octet-stream" )) {
String contentDisposition = headers.getContentDisposition();
String url =
null ;
if
(contentDisposition != null ) {
url = URLUtil.parseContentDisposition(contentDisposition);
}
if
(url == null ) {
url = mUrl;
}
String newMimeType = guessMimeTypeFromExtension(url);
if
(newMimeType != null ) {
mMimeType = newMimeType;
}
}
else if
(mMimeType.equals( "text/vnd.wap.wml" )) {
}
else {
if
(mMimeType.equals( "application/vnd.wap.xhtml+xml" ) ||
mMimeType.equals( "application/xhtml+xml" )) {
mMimeType =
"text/html" ;
}
}
}
}
|
分享到:
相关推荐
支持wml1.1标准 支持手机wap浏览和通过手机发表日志 .支持trackback引用发送和接收 网站间互通更方便 .采用smarty模版引擎,程序与模版分离,方便修改,用户可自定义界面 .采用目前相对最安全的数据库防下载技术 ...
三、 3G版另外的一个特点是 实现PC普通浏览器也可以登录手机网站(即平台通用性),不仅打破电脑无需安装任何特殊浏览器(例如 OPERA等手机网站常用浏览器)即可及时访问手机网站,并且实现了PC与手机内容同步,通过...
三、 3G版另外的一个特点是 实现PC普通浏览器也可以登录手机网站(即平台通用性),不仅打破电脑无需安装任何特殊浏览器(例如 OPERA等手机网站常用浏览器)即可及时访问手机网站,并且实现了PC与手机内容同步,通过...
QuickWAP的开发集成了微软的ASP、VB、ActiveX、Windows2003(2007)、IIS6.0(5.0)、Access、MSSQL2000(2005)、SQL和WAP的WML、XHTML MP语言,以及ASPJPEG、JMail组件、CSS语言等技术于一体,其中以微软的各种技术为核心...
QuickWAP的开发集成了微软的ASP、VB、ActiveX、Windows2003(2007)、IIS6.0(5.0)、Access、MSSQL2000(2005)、SQL和WAP的WML、XHTML MP语言,以及ASPJPEG、JMail组件、CSS语言等技术于一体,其中以微软的各种技术为核心...
继续ASP开源之路,稳定、安全、强大的核心程序,对于有网站设计知识和程序爱好者可以随心所欲进行修改,方便建立具有自已特色的站点。 酷睿股票私募网站管理系统,最大的优势不仅在于有全国首创的WAP手机访问系统...
--[优先级2]移动网关提供有UA情况下,有些浏览器不支持wap1.0/2.0,只支持电脑访问如苹果的Safari浏览器,有以下UA关键字进入电脑版--> |iPhone" /> <!--[优先级3]移动网关提供有UA情况下,当网站进入不同版本...
7.7.1 MSXML对命名空间和模式的支持 7.7.2 数据类型 7.8 图书目录中的变化 7.8.1 为什么烦恼 7.8.2 重铸DTD 7.8.3 模式协调 7.9 小结 第8章 链接和查询 8.1 XML 信息集合 8.1.1 信息类型 8.1.2 信息集合的...
7.7.1 MSXML对命名空间和模式的支持 7.7.2 数据类型 7.8 图书目录中的变化 7.8.1 为什么烦恼 7.8.2 重铸DTD 7.8.3 模式协调 7.9 小结 第8章 链接和查询 8.1 XML 信息集合 8.1.1 信息类型 8.1.2 信息集合的...
7.7.1 MSXML对命名空间和模式的支持 7.7.2 数据类型 7.8 图书目录中的变化 7.8.1 为什么烦恼 7.8.2 重铸DTD 7.8.3 模式协调 7.9 小结 第8章 链接和查询 8.1 XML 信息集合 8.1.1 信息类型 8.1.2 信息集合的...
7.7.1 MSXML对命名空间和模式的支持 228 7.7.2 数据类型 229 7.8 图书目录中的变化 230 7.8.1 为什么烦恼 230 7.8.2 重铸DTD 231 7.8.3 模式协调 236 7.9 小结 240 第8章 链接和查询 241 8.1 XML 信息集合 241 8.1.1...
<br>7.1 使用可移动设备软件模拟器 7.2 无线应用协议简介 7.3 建立WML页面 7.3.1 配置IIS 7.3.2 WML和XML 7.3.3 创建卡片集 7.3.4 用WML链接文件 7.4 使用ASP.NET可移动控件 ...
<br>7.1 使用可移动设备软件模拟器 7.2 无线应用协议简介 7.3 建立WML页面 7.3.1 配置IIS 7.3.2 WML和XML 7.3.3 创建卡片集 7.3.4 用WML链接文件 7.4 使用ASP.NET可移动控件 ...
<br>7.1 使用可移动设备软件模拟器 7.2 无线应用协议简介 7.3 建立WML页面 7.3.1 配置IIS 7.3.2 WML和XML 7.3.3 创建卡片集 7.3.4 用WML链接文件 7.4 使用ASP.NET可移动控件 ...
<br>7.1 使用可移动设备软件模拟器 7.2 无线应用协议简介 7.3 建立WML页面 7.3.1 配置IIS 7.3.2 WML和XML 7.3.3 创建卡片集 7.3.4 用WML链接文件 7.4 使用ASP.NET可移动控件 ...
<br>7.1 使用可移动设备软件模拟器 7.2 无线应用协议简介 7.3 建立WML页面 7.3.1 配置IIS 7.3.2 WML和XML 7.3.3 创建卡片集 7.3.4 用WML链接文件 7.4 使用ASP.NET可移动控件 ...
behind文件派生多个页面 6.3.4 编译完整的ASP.NET页面 6.4 小结 <br/>第7章 用可移动控件为可移动设备服务 <br/>7.1 使用可移动设备软件模拟器 7.2 无线应用协议简介 7.3 建立WML页面 ...