前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android开发笔记(一百五十一)WebView与JavaScript交互的四种形式

Android开发笔记(一百五十一)WebView与JavaScript交互的四种形式

作者头像
aqi00
发布2019-01-18 15:16:30
1.2K0
发布2019-01-18 15:16:30
举报
文章被收录于专栏:老欧说安卓老欧说安卓

WebView如果作为简单的网页浏览器,对于一般的浏览行为来说,已经足够了。可做为企业开发者,你的App通常要嵌入自家公司的网页,如此一来,还得考虑App与Web之间的消息传递,这就涉及到App的原生代码与Web的JS代码之间的通信了。 App与Web做为消息通信的双方,具体的交互行为分为四类,包括:App通知Web执行某项动作、App主动从Web获取信息、Web通知App执行某项动作,Web主动从App获取信息,这四种行为详细说明如下:

1. App通知Web执行某项动作

Web提供一个JavaScript方法,然后App由WebView调用loadUrl加载该JS方法,具体的App代码如下所示:

代码语言:javascript
复制
		wv_js.loadUrl("javascript:showMsgFromWeb()");

该行为的执行效果如下图所示,App通知JS调用showMsgFromWeb方法,该方法弹出了一个alert消息框。

2. App主动从Web获取信息

WebView对象调用evaluateJavascript方法,该方法通过回调接口ValueCallback获得JS的返回串,具体的App代码如下所示:

代码语言:javascript
复制
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
			// evaluateJavascript该方法为4.4以后引入
			wv_js.evaluateJavascript("getMsgFromWeb()", new ValueCallback<String>() {
				@Override
				public void onReceiveValue(String value) {
					AlertDialog.Builder builder = new AlertDialog.Builder(WebScriptActivity.this);
					builder.setTitle("来自安卓的对话框").setMessage(UnicodeToString(value));
					builder.create().show();
				}
			});
		} else {
			Toast.makeText(this, " Android4.4之后才支持该功能", Toast.LENGTH_SHORT).show();
		}

该行为的执行效果如下图所示,App通知JS调用getMsgFromWeb方法,获得返回消息后再由App自行弹窗。

3. Web通知App执行某项动作

App需要定义一个专门给JS使用的类,并在该类中实现JS要调用的方法,具体的类代码如下所示:

代码语言:javascript
复制
	private final class Client {
		@JavascriptInterface
		public void showMsgFromAndroid(String msg) {  //如要返回值可把void改为String等等类型
			AlertDialog.Builder builder = new AlertDialog.Builder(WebScriptActivity.this);
			builder.setTitle("来自安卓的对话框").setMessage(msg);
			builder.create().show();
		}

		@JavascriptInterface
		public String getMsgFromAndroid(String msg) {
			return "这是Android返回的字符串:"+msg;
		}
	}

接着还要调用WebView对象的addJavascriptInterface方法,给这个新类注册一个实例名,然后JS才能通过该实例名调用App的方法。注册实例名的代码如下所示:

代码语言:javascript
复制
		wv_js.addJavascriptInterface(new Client(), "client");

该行为的执行效果如下图所示,Web调用App的showMsgFromAndroid方法,该方法弹出了一个AlertDialog。

4. Web主动从App获取信息

该行为的主要流程同行为三,区别在于App方法的返回值类型由void改为String,然后JS即可从App获得返回信息。 该行为的执行效果如下图所示,Web调用App的getMsgFromAndroid方法获得字符串,然后Web把该消息以alert方式弹窗。

下面是演示WebView与JavaScript交互用到的html文件源码:

代码语言:javascript
复制
<html>
<head>
<meta name="viewport" content="width=device-width, target-densitydpi=device-dpi" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript">
   function showMsgFromWeb(){
      alert("这是网页弹出的对话框");
   }
   function getMsgFromWeb(){
      return "这是网页返回的字符串";
   }
   function showMsgInAndroid(){
      var result = client.getMsgFromAndroid("这是网页给的参数");
      alert(result);
   }
   function showAndroidDialog(){
       client.showMsgFromAndroid("网页要求安卓弹窗");
   }
</script>
</head>
<body>
<font size='5'>测试js使用</font><br>
<button onclick="javascript:showAndroidDialog()"><font size='5'>让android弹窗</font></button><br>
<button onclick="javascript:showMsgInAndroid()"><font size='5'>调用Android方法获得字符串</font></button><br>
</body>
</html>

为了区分对话框是App来源的弹窗还是Web来源的弹窗,这里重写了WebChromeClient的onJsAlert方法,通过setTitle方法区分本次弹窗的来源途径。重写后的方法代码如下所示:

代码语言:javascript
复制
		public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
			String title = mTitle;
			if (title==null || title.length()<=0) {
				title = "来自网页的对话框";
			}
			AlertDialog.Builder builder = new AlertDialog.Builder(WebScriptActivity.this)
					.setTitle(title).setMessage(message)
					.setPositiveButton("确定",
							new DialogInterface.OnClickListener() {
								@Override
								public void onClick(DialogInterface dialog, int which) {
									result.confirm();
								}
							});
			//setCancelable要设置为false,点击对话框外部时不让关闭对话框
			//不然JsResult的confirm方法没有得到执行,网页上的其它控件就不可使用
			builder.setCancelable(false).create().show();
			return true;
		}

另外还需注意WebView与JavaScript相互调用的几个要点: 1. WebView要调用setWebChromeClient方法设置JS的解释客户端,从而避免JS中alert方法不弹窗的问题,因为JS页面的渲染需要WebChromeClient去实现。 2. 如果JS调用App代码时报错“Uncaught TypeError: Object [object Object] has no method”,那是因为Android4.2以上版本默认不开放JS调用本地方法的权限,得给开放JS调用的方法加上“@JavascriptInterface”注释,该注释允许JS代码访问APP的指定方法。 3. evaluateJavascript是Android在4.4.2之后才引入的新方法,如果是4.4.2之前的Android版本,需要注意做兼容处理。 4. JS调用App方法,返回值中的中文是正常;但App获取JS方法,返回值的中文却是“\u”打头的字符串,所以要先将JS返回的字符串做转义处理,转义后的字符串才是App能够处理的正常汉字。 5. 如果App与JS存在嵌套调用(即A调用B,B内部又去调用A),那么Android4.4.2之后务必要保证两个调用在同一个线程中,不然运行时会报错“java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread.”。具体的解决方法是:调用WebView对象的post方法,然后在post的Runnable任务中再去调用JS方法,例子代码如下所示:

代码语言:javascript
复制
	private final class Contact {
		//网页的JS调用App的showcontacts方法,然后showcontacts内部又去调用JS的show方法
		@JavascriptInterface
		public void showcontacts() {
			wv_local.post(new Runnable() {
				@Override
				public void run() {
					wv_local.loadUrl("javascript:show()");
				}
			});
		}
	}

点此查看Android开发笔记的完整目录

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年01月17日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. App通知Web执行某项动作
  • 2. App主动从Web获取信息
  • 3. Web通知App执行某项动作
  • 4. Web主动从App获取信息
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档