Android(安卓)WebView系列(二)Android和JS互调,BridgeWebView的使用。
前言
上篇介绍了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) }}
WebView在Android4.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互相调用方法。在大前端概念的趋势下,原生Android和H5(JS)的联系会越来越紧密。下篇将介绍在重构过程中WebView上遇到的问题,以及WebView最让人关系的内存泄漏问题以及解决方案。对于H5和Java层结合的混合开发Hybrid的研究也将在以后的WebView系列中做介绍。
Android WebView系列(一)WebView的基本使用
更多相关文章
- Android进程与线程基本知识
- Android(安卓)Binder入门指南之defaultServiceManager()的实现
- APK的自我保护
- Android图文详解属性动画
- Application Fundamentals
- android android屏幕禁止休眠和锁屏的方法
- 详解 Android(安卓)的 Activity 组件
- 【Unity3D】与Android相互传递消息
- android的Handler