前言

上篇介绍了WebView的基本使用,WebView使用中常用的类和方法。本篇将介绍WebView中Android原生Js之间交互。以及它们之间通信桥梁JsBridge

1.Android调用JS

Android调用JS有两种方法,第一种是通过loadUrl()方法,第二种是通过evaluateJavascript()

1-1.loadUrl()示例

首先新建index.html放在android工程的assets目录下。

Android WebView系列(二)Android和JS互调,BridgeWebView的使用。_第1张图片

看下Html中的JS代码和Android中调用,JS代码相对比较简单。

<html>    <head>        <meta charset="utf-8" />        <title>WebView测试title>    head>    <script type="text/javascript">                function androidCallJs(){            alert("android 调用了 JS了")        }    script>html>

看下Android中如何实现调用JavaScript代码的。

布局文件:

id="@+id/webview"    android:layout_width="match_parent"    android:layout_height="wrap_content" />

Kotlin代码:

   /*初始化webview*/   val webView = getView(R.id.webview)   /*设置webview选项参数*/   val webSetting = webView!!.settings   /*设置webview可以调用javascript代码*/   webSetting.javaScriptEnabled = true   /*设置javascript可以自动弹弹窗*/   webSetting.javaScriptCanOpenWindowsAutomatically = true   /*加载html,这里android_asset是固定写法*/   webView!!.loadUrl("file:///android_asset/index.html")   callJsBtn = getView(R.id.callJsBtn)   callJsBtn!!.setOnClickListener {     /*点击调用Js方法*/     webView!!.loadUrl("javascript:androidCallJs()")    }    /*webview是加载整个html作用,内容的渲染需要使用它的功能辅助类WebviewChromClient类去实现*/    webView!!.webChromeClient = object : WebChromeClient() {      override fun onJsAlert(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean {         val b = AlertDialog.Builder(this@MainActivity);         b.setTitle("Android Call Js")         b.setMessage(message)         b.setPositiveButton("确定",object :DialogInterface.OnClickListener{                    override fun onClick(dialog: DialogInterface?, which: Int) {                  result!!.confirm()              }          })          b.setCancelable(false)          b.create().show()          return true      }  }

Android WebView系列(二)Android和JS互调,BridgeWebView的使用。_第2张图片

1-2.evaluateJavascript()示例

<html>    <head>        <meta charset="utf-8" />        <title>WebView测试title>    head>    <script type="text/javascript">                function androidCallJs(){            alert("android evaluateJs 调用了 JS了")            return "Android你能收到消息吗?"        }    script>html>
callJsBtn!!.setOnClickListener {    /*第二种方法调用JS*/    webView!!.evaluateJavascript("javascript:androidCallJs()", object : ValueCallback<String> {       /*Js返回的值*/       override fun onReceiveValue(value: String?) {                   ToastUtils.show(value!!)       }     })      // webView!!.loadUrl("javascript:androidCallJs()")}

Android WebView系列(二)Android和JS互调,BridgeWebView的使用。_第3张图片

只要将第一种方法loadUrl()更换为evaluateJavascript()方法即可。这种方法相比较第一种方法,能够接收到JS返回值,loadUrl()只能显示。

2.JS调用Android

2-1.WebView提供方法 addJavascriptInterface() 将Js和Android建立映射关系。

2-1-1.Html声明映射对象以及Android被调用的方法

<html>    <head>        <meta charset="utf-8" />        <title>JS调用Android测试1title>    head>    <script type="text/javascript">      function JsCallAndroid(){                testHello.helloJs("JsCallAndroid")      }    script>    <body>        <button type="button" id="btn" onclick="JsCallAndroid()">点击调用Android代码button>    body>html>

2-1-2.定义与Js映射关系的Android类

/* * 创建者:    Ho * 创建时间:  2018/6/6 on 19:46 * 描述:      Js映射的Android类 * 其他说明: 无 */class AndroidToJs : Object() {    //注解映射    @JavascriptInterface    fun helloJs(msg: String) {        ToastUtils.show("Js 调用了 Android helloJs方法了")    }}

2-1-3.Kotlin添加Js和Android映射关系

/*初始化webview*/webView = getView(R.id.webview)/*设置webview选项参数*/val webSetting = webView!!.settings/*设置webview可以调用javascript代码*/webSetting.javaScriptEnabled = true/*加载html*/webView!!.loadUrl("file:///android_asset/index.html")/*Webview添加Js和Android映射关系*/webView!!.addJavascriptInterface(AndroidToJs(), "testHello")

AndroidToJs()是Android的映射类。Kotiln的写法。“testHello”是映射到JS的映射类的对象,名字可以随意取。

Android WebView系列(二)Android和JS互调,BridgeWebView的使用。_第4张图片

2-2. WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截消息解析。

<html>     <head>         <meta charset="utf-8">         <title>JS调用Android测试1title>      head>      <script>         function clickprompt(){         // 调用prompt()  定义js和android通信协议         var result=prompt("js://test?param1=hello11¶m1=hello22");         alert("test" + result);        }      script>            <body>         <button type="button" id="btn" onclick="clickprompt()">点击调用Android代码button>        body>    html>
webView!!.webChromeClient = object : WebChromeClient() {    override fun onJsPrompt(view: WebView?, url: String?, message: String?, defaultValue: String?, result: JsPromptResult?): Boolean {         val uri = Uri.parse(message)         // 如果uri协议 = 预先约定的 js 协议,解析参数         if (uri.scheme == "js") {             // 如果 authority  = 预先约定协议里的 webview,即代表都符合约定的协议             // 所以拦截url,下面JS开始调用Android需要的方法             if (uri.authority == "webview") {             // 执行JS所需要调用的逻辑             ToastUtils.show("Js 调用了 Android 中 helloToJS代码")             // 可以在协议上带有参数并传递到Android上             val params = HashMap<String, String>()             var collection = uri!!.queryParameterNames             //参数result:代表消息框的返回值(输入值)             result!!.confirm("js调用了Android的方法成功啦")            }            return true           }           return super.onJsPrompt(view, url, message, defaultValue, result)     }}

WebViewAndroid4.2以下版本产生安全问题有一种情况就是通过第一种添加Js和Android映射关系的方式。第二种方式就是较为安全,不会产生安全漏洞问题。但是要Android和Js约定一个协议通信,相对实现起来比较复杂,onJsAlert()和onJsConfirm()和上述实现方式一样。

3.BridgeWebView(Hybrid)

BridgeWebView,继承了WebView类,实现了WebViewJavascriptBridge接口。各位大佬一看就知道是一个Js和Android通信的封装类。这里介绍下它的使用方式。

3-1.Gradle引入

compile 'com.github.lzyzsd:jsbridge:1.0.4'

3-2.使用方法

3-2-1.自定义JS事件回调类

private class MyHadlerCallBack extends DefaultHandler {   @Override   public void handler(String data, CallBackFunction function) {       if (function != null) {           Toast.makeText(JsBridgeVoteActivity.this, "自定义类继承DefaultHandler:" + data, Toast.LENGTH_SHORT).show();         }     }}

3-2-2.自定义JS事件回调类

/*创建实例*/BridgeWebView webView = new BridgeWebView(this);/*设置默认回调处理类*/webView.setDefaultHandler(new MyHadlerCallBack());/*注册Js和android之间通信的事件*/webView.registerHandler("openLogin", (data, function) -> openLogin());

以上面的代码为例,在Android中注册了事件 “openLogin”,这里也需要在Html页面的Js代码中进行注册相同的事件名称 “openLogin”。意味着在Html页面上用户(未登录情况下)触发登录操作。登录事件要在boolean isBindPhone代码中完成。

private void openLogin() {     new LoginDialog(this, new LoginDialog.OnLoginCallBack() {         @Override         public void login() {             HashMap params = new HashMap<>();             /*method是和js约定,这是调用方法,后面是登录成功操作*/             params.put("method", "loginSuccess");             /*webView通知js已经登录成功*/             webView.callHandler("call", new Gson().toJson(params), data ->{                             });          }   }).show();}

Js调用Android登录方法,Android端登录成功后通过webView.callHandler方法通知H5页面(Js)客户端登录成功,做相应的操作即可。BridgeWebView的使用方法就是这么简单,内部已经将通信机制封装好。

结尾

本篇介绍了WebView上Js和Android互相调用方法。在大前端概念的趋势下,原生AndroidH5(JS)的联系会越来越紧密。下篇将介绍在重构过程中WebView上遇到的问题,以及WebView最让人关系的内存泄漏问题以及解决方案。对于H5和Java层结合的混合开发Hybrid的研究也将在以后的WebView系列中做介绍。

Android WebView系列(一)WebView的基本使用

更多相关文章

  1. android android屏幕禁止休眠和锁屏的方法
  2. Android向服务器传接和接收数据的方法汇总
  3. android spinner默认样式不支持换行和修改字体样式 的解决方法
  4. Android中创建对话框(确定取消对话框、单选对话框、多选对话框)
  5. [Android][Android Studio] *.jar 与 *.aar 的生成与*.aar导入项
  6. 从零开始--系统深入学习android(实践-让我们开始写代码-Android框
  7. 经典Android系统源代码
  8. Android防止内存溢出浅析/应用自动更新功能的代码实现
  9. android待机详细结合代码分析(二)

随机推荐

  1. android每日一问【2011-09-17】
  2. android 利用shape实现环形进度条
  3. Android下native code(C++)的编译,NDK的使用
  4. 新书内容连载(3):Android(安卓)SDK中常用命
  5. android gravity and LinerarLayout for
  6. 跟我学Android4 之 第一部分:Android入门
  7. Android(安卓)SDK r20.x更新时,没有Androi
  8. android Makefile
  9. android中根据控件宽度,实现展示文本内容,
  10. android shape 代码实现按钮背景