前言

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

1.Android调用JS

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

1-1.loadUrl()示例

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

看下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      }  }

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()")}

只要将第一种方法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的映射类的对象,名字可以随意取。

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进程与线程基本知识
  2. Android(安卓)Binder入门指南之defaultServiceManager()的实现
  3. APK的自我保护
  4. Android图文详解属性动画
  5. Application Fundamentals
  6. android android屏幕禁止休眠和锁屏的方法
  7. 详解 Android(安卓)的 Activity 组件
  8. 【Unity3D】与Android相互传递消息
  9. android的Handler

随机推荐

  1. Android: Type Method 'NewStringUTF' co
  2. MediaBrowserService 音乐播放项目《IT蓝
  3. TextView获取父控件的绘图状态
  4. Android(安卓)中的显示单位
  5. Android各版本间API的差异 - (Share)Acti
  6. 使用SQLiteOpenHelper 和使用ContentProv
  7. Mono for Android(安卓)实现高效的导航
  8. DexClassLoader 实现 Android(安卓)插件
  9. Android中EditText输入字数统计和限制
  10. Android进阶---Android(安卓)Webview重定