码迷,mamicode.com
首页 > 编程语言 > 详细

一处疑难杂症的术后总结:WebView和JavaScript之间的交互

时间:2015-03-20 01:28:37      阅读:264      评论:0      收藏:0      [点我收藏+]

标签:javascript   webview   html5   

最近在公司里参与了M3项目的开发,这个项目是使用HTML5开发的前端页面,在开发完毕后,把项目地址写入AndroidiOS的壳源码里面,这样当应用被打开时候自动载入项目首页的URL。这种做法对于用户来说,可以不用更新客户端,对于开发人员来说,发现问题可以及时修复并更新,当然这也是B/S软件的优点。

在这个APP里面是有个拨号功能的,即点击界面上的电话小图标,可以直接通过手机拨出号码。昨天同事丁丁告知我们这个APP有个BUG:在iOS里面拨号是没有问题的,但是在Android里面拨号时,会跳转到一个报错页面,类似于我们常见的404页面。无法实现拨号操作。我们的代码写的就是常见的tel:19212345678这种。我先讲一下我们的处理过程。

话说知之为知之,不知百度知。所以我和同事明明先到百度上面搜索了一下,得到以下的结果:

在开源中国社区里面,有人建议在tel:后面加上双斜杠,类似tel://19212345678。我看到后立马试了一下,不行。

在另一个网站里面,有人建议在号码背后加上微信的官网地址。类似tel:19212345678#weixin.qq.com。我试了一下,还是老样子。

同事们聚在一起看了下,这段拨号的代码,在iOS上面是没有任何问题的,在微信的自带的浏览器里面是没有任何问题的,在Android手机自带的浏览器里面也是没有任何问题的。唯独在打包成APP后访问时出了问题!

后来同事华华给我发来一段代码,这个是在设置属性的时候重写shouldOverrideUrlLoading(WebView view, String url)这个方法。代码大意是,先判断传入的URL是不是以“tel:”开头的,如果是的,那就执行拨号操作;如果不是的,那就执行加载URL的操作。我加进去试了一下,这下可以拨号了,但是不能高兴得太早。还发现有个小问题,在拨号界面弹出的同时,那个类似404的错误界面还是会弹出来的,只不过是被拨号的界面给遮挡住了。在通话完毕挂机之后,那个错误界面又会出来。


今天丁丁又在催问这个拨号的问题了,我说我只完成了50%,还有个小问题还没解决,我还不满意。丁丁狡猾地说道:如果你今天不能解决,我也不满意。下午我把手头上的任务完成了之后,就又开始研究这个奇葩的问题了。同事涛涛和华华也过来协助把脉。

同事涛涛在QQ上给我发的几个网址,我都点开一一试了下。

第一个是重写shouldOverrideUrlLoading(WebView view, String url)这个方法的,我回复说昨天已经试过了,能生效但是错误的界面还是会跟着弹出,体验不是很好;

第二个是使用wati协议拨打电话。类似<a href="wtai://wp//mc;10086">拨打10086 </a>  ,我回复说这个也试了,也是不起作用。

在同事华华的建议下,我把模拟器打开了,研究了下载整个拨号操作中的过程,花费了一些时间,但并没有发现什么异常。shouldOverrideUrlLoading这段代码的判断是对的。

正当一筹莫展的时候,华华忽然想起了一年前和另一位同事做的户型图展示功能,当时也是由于技术的局限性不得不使用js调用了AndroidAPI,想看看能不能仿照那个问题的解决思路来解决这个拨号的问题。

这个WebViewjs的交互是在jsp页面上定义个函数。在Android壳源码里面通过addJavascriptInterface(new JavascriptInterface(this),"jsInterface")来添加定义在jsp上面的js接口。当然前提是要在壳源码里面添加javascript支持。这个我已经加了。在jsp里面,原来的<a href=”tel:XXX”>已经被改造成了个点击事件,具体的执行内容写在了js函数里面,从而避免了会被识别为个超链接而跳到一个404页面。如果你认为在这里就成功了,那也太容易了。试了一下,点击图片后页面是一明一暗地闪烁,并没有执行拨号操作。在Logcat看到,它其实是没取到值的。是在取值的时候的时候出了问题?我把取值的${clientInfoVO.clientMobile}换成了<s:property value=‘clientMobile‘ />,竟然就取到值了!

剩下的就是针对AndroidiOS两种操作系统进行判断了。到此为止,这个问题终于解决了,我长长地吁了一口气。


感谢你有足够的耐心看完了上面这长长的流水账,如果你也遇到了和我类似的问题,那么你是幸运的。下面我总结下WebViewjs交互这类的问题的解决办法:

1、在Android壳源码里面添加权限声明:

<uses-permission android:name="android.permission.CALL_PHONE" />

需要声明打电话的权限并获取用户授权,不然不能通过Android壳去执行拨号操作。如果你要是要发短信,那就是短信相关的权限啦,灵活处理;

2、在Android壳源码里面启用JavaScript支持:

contentWebView.getSettings().setJavaScriptEnabled(true);

这样才能在壳源码里面调用web页面的js函数

3、重写shouldOverrideUrlLoading(WebView view, String url)方法,对符合和不符合的两种URL进行判断,并执行不同的操作。示例代码如下:

public boolean shouldOverrideUrlLoading(WebView view, String url) {
		        if (url.startsWith("tel:")) { 
		                Intent intent = new Intent(Intent.ACTION_VIEW,
		                        Uri.parse(url)); 
		                startActivity(intent);             
		                return false;
		        } else {
		        	view.loadUrl(url);
			        return true;
				}
		    }		

4、在web页面的链接改造成调用js函数,在函数里面执行类似window.js接口名.js函数名()。示例代码如下:

function exitSys(tel){
		window.jsInterface.exitSys(tel);
	}

5、在Android壳源码里面对应加上js接口声明,比如我的名称是jsInterface,就是在第四步里面写的js接口名:

contentWebView.addJavascriptInterface(new JavascriptInterface(this),
				"jsInterface");

6、在JavascriptInterface类里面声明与js对应的方法。这里我就写在Android里面执行拨打电话的代码。例如:

public void exitSys(String number) {
			   Intent intent = new Intent(Intent.ACTION_CALL,Uri.parse("tel:"+number));  
               startActivity(intent);  	
		}

7、需要被调用的这个js里面如果需要动态传参,给这个js函数相关的参数值赋值最好用<s:property >,而不要用${}。否则可能会莫名其妙地取不到值;(如果你在模拟器上测试,出现invalid MMI code的时候,也可以说明成功了。建议你可以换用真机去测试)

8、在web页面加上浏览器判断。如果是iOS浏览器,就继续沿用之前万能的<a href=”tel:XXX”>,如果是Android浏览器,就执行自定义的这个js函数。

一处疑难杂症的术后总结:WebView和JavaScript之间的交互

标签:javascript   webview   html5   

原文地址:http://blog.csdn.net/hbxfyxw/article/details/44474063

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!