前言

现在业务稍微大一点的公司,基本上都会引入android与H5交互的方式开发,或者是引入Hybrid框架,更有甚者直接全部采用Js开发成Web App形式,就是看中其开发成本更低(跨平台),更新风险更小的优势。目前移动端开发市场的遇冷,除了android初级人才过多之外,还有就是前端技术的崛起,挤占了native开发的空间,不过仔细想想,在互联网的意义上,移动端的App其实也属于前端。。。所以顺应技术的浪潮,拥抱变化才能使自己立于不败之地。附上源码地址

界面展示

图中的上半部分是android原生界面,下半部分是webview加载html的页面,可以看到,两边可以相互传递参数,并且调用对方的代码块了。下面我把完成的代码先贴出来,有基础的同学可以直接copy源码然后自己调试看看,没基础的同学别急,听我一个一个解析。

Android调用Js

通过WebView有loadUrl()evaluateJavascript()两种方法调用Js方法。

这里采用加载本地assets中的html文件进行调试

1、loadUrl() 方式

JsMethod.html

<html><head><meta http-equiv="Content-Type" charset="UTF-8"/><script type="text/javascript">var s = '我来自Js方法';function javatojscallback(param){document.getElementById("textshow").innerHTML = (param);//window.android.JsToJavaInterface(s)}</script></head><body><h3>Js Method</h3><h3 id="textshow">调用结果</h3></body></html>
复制代码

window.android.JsToJavaInterface(s)是Js调用android的方法,由于loadUrl()不能从Js返回数据,可以让Js回调android的方法回传参数。

MainActivity.java

...private void initView() {javaMethod = new JavaMethod(this);webView = new WebView(this);WebSettings settings = webView.getSettings();settings.setDomStorageEnabled(true);settings.setJavaScriptEnabled(true);settings.setBlockNetworkImage(false);frameLayout.addView(webView);webView.loadUrl("file:///android_asset/JsMethod.html");}
...
复制代码

调用Js

webView.loadUrl("javascript:javatojscallback('我来自Java')");
复制代码

2、evaluateJavascript()

<html><head><meta http-equiv="Content-Type" charset="UTF-8"/><script type="text/javascript">var s = '我来自Js方法';function javatojswith(param){document.getElementById("textshow").innerHTML = (param);return s;}</script></head><body><h3>Js Method</h3><h3 id="textshow">调用结果</h3></body></html>
复制代码

调用Js

    webView.evaluateJavascript("javascript:javatojswith('我来自Java')",new ValueCallback<String>() {@Overridepublic void onReceiveValue(String s) {textShow.setText(s);}});
复制代码

相信已经大家已经注意到,被调用的Js方法是有返回值的,如果是采用loadUrl()调用,返回值也会用loadUrl()载入,直接显示在WebView上,这显然是不对的,我们只想隐形的接收返回值,而evaluateJavascript()就提供了这样的隐形接收方式,不会调用到loadUrl()

需要注意的是,evaluateJavascript()只能在android 4.4之后才能调用。

Js调用Android

Js通过WebView有三种方式调用android方法

1、addJavascriptInterface

<html><head><meta http-equiv="Content-Type" charset="UTF-8"/><script type="text/javascript"></script></head><body><h3>Js Method</h3><h3 id="textshow">调用结果</h3><input type="button" value="JavascriptInterface" onclick="window.android.JsToJavaInterface('我来自Js')"/></body></html>
复制代码

JavaMethod.java

public class JavaMethod {private MainActivity mainActivity;private Handler uiHandler;public JavaMethod(MainActivity mainActivity) {this.mainActivity = mainActivity;uiHandler = new Handler(Looper.getMainLooper());}@JavascriptInterfacepublic void JsToJavaInterface(final String param) {uiHandler.post(new Runnable() {@Overridepublic void run() {mainActivity.setTextShow("from JavaInterface: " + param);}});}
}
复制代码

这里我把Js调用Java的方法分离出来到一个JavaMethod类中,然后通过Looper.getMainLooper()获取主线程Handler,统一采用接口形式更新界面。

MainActivity.java

...private void initView() {...settings.setJavaScriptEnabled(true);webView.addJavascriptInterface(javaMethod,"android");frameLayout.addView(webView);webView.loadUrl("file:///android_asset/JsMethod.html");}public void setTextShow(String str) {textShow.setText(str);}
...
复制代码

在android4.2之前有个严重漏洞,Js通过webview获取android对象后,可以调用到其他系统方法,为了避免这个漏洞,在4.2之后,只能调用到@JavascriptInterface注释过的方法。

2、shouldOverrideUrlLoading

通过WebViewClient中的shouldOverrideUrlLoading拦截url,制定一个对应协议。

<html><head><meta http-equiv="Content-Type" charset="UTF-8"/><script type="text/javascript"></script></head><body><h3>Js Method</h3><h3 id="textshow">调用结果</h3><input type="button" value="shouldOverrideUrlLoading" onclick="document.location = 'js://jstojava?arg1=1号参数&arg2=2号参数'"/></body></html>
复制代码

JavaMethod.java

...public WebViewClient getWebViewClient() {WebViewClient webViewClient = new WebViewClient(){@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {Uri uri = Uri.parse(url);// 一般根据scheme(协议格式) & authority(协议名)判断// url = "js://jstojava?arg1=1&arg2=2"if(uri.getScheme().equals("js")) {if(uri.getAuthority().equals("jstojava")) {final String param1 = uri.getQueryParameter("arg1");final String param2 = uri.getQueryParameter("arg2");uiHandler.post(new Runnable() {@Overridepublic void run() {mainActivity.setTextShow("arg1="+param1+" arg2="+param2);}});}return true;}return super.shouldOverrideUrlLoading(view, url);}};return webViewClient;}
...
复制代码

MainActivity.java

...private void initView() {javaMethod = new JavaMethod(this);webView = new WebView(this);WebSettings settings = webView.getSettings();settings.setDomStorageEnabled(true);settings.setJavaScriptEnabled(true);settings.setBlockNetworkImage(false);webView.setWebViewClient(javaMethod.getWebViewClient());webView.addJavascriptInterface(javaMethod,"android");frameLayout.addView(webView);webView.loadUrl("file:///android_asset/JsMethod.html");}
...
复制代码

这种方式没有版本限制和漏洞,不过没有返回值,如果Js调用后需要android返回就得使用loadUrl()或者evaluateJavascript()回传对应的接收方法了。值得一提的是,这种方式便于和IOS通用一套协议,简便Js端的代码量。

3、onJsAlert()、onJsConfirm()、onJsPrompt()

通过 WebChromeClient 中的onJsAlert()、onJsConfirm()、onJsPrompt()拦截Js中的alert()、confirm()、prompt() 消息。而alertconfirmprompt代表Js中三种常用提示框,第一种没有返回值,第二种返回布尔值,第三种可返回任意值。由于考虑到灵活性,所以我们可以直接实现对prompt的拦截即可。

<html><head><meta http-equiv="Content-Type" charset="UTF-8"/><script type="text/javascript">function jstojavaprompt(param){result = prompt(param);document.getElementById("textshow").innerHTML = (result);}</script></head><body><h3>Js Method</h3><h3 id="textshow">调用结果</h3><input type="button" value="onJsPrompt" onclick="jstojavaprompt('js://jstojava?arg3=3号参数&arg4=4号参数')"/></body></html>
复制代码

JavaMethod.java

...public WebChromeClient getWebChromeClient() {WebChromeClient webChromeClient = new WebChromeClient(){@Overridepublic boolean onJsPrompt(WebView view, String url, String message, String defaultValue, final JsPromptResult result) {Uri uri = Uri.parse(message);if(uri.getScheme().equals("js")) {if(uri.getAuthority().equals("jstojava")) {final String param3 = uri.getQueryParameter("arg3");final String param4 = uri.getQueryParameter("arg4");uiHandler.post(new Runnable() {@Overridepublic void run() {mainActivity.setTextShow("arg3="+param3+" arg4="+param4);result.confirm("我来自onJsPrompt");}});}return true;}return super.onJsPrompt(view, url, message, defaultValue, result);}};return webChromeClient;}
...
复制代码

MainActivity.java

...private void initView() {javaMethod = new JavaMethod(this);webView = new WebView(this);WebSettings settings = webView.getSettings();settings.setDomStorageEnabled(true);settings.setJavaScriptEnabled(true);settings.setBlockNetworkImage(false);webView.setWebChromeClient(javaMethod.getWebChromeClient());webView.addJavascriptInterface(javaMethod,"android");frameLayout.addView(webView);webView.loadUrl("file:///android_asset/JsMethod.html");}
...
复制代码

协议的方式与shouldOverrideUrlLoading拦截url时类似,在对应线程处理完业务后,可将结果通过result.confirm()返回给Js。

总结

以上的交互方法各有利弊,主要是由于android版本的限制,没有版本限制的方法稍显麻烦,但是通用,一劳永逸,大家可以从业务覆盖的机型来考虑引入哪种方式来与Js交互。

源码地址

源码已经集成文中的回调方式,感兴趣的同学可以看下。

最后附上一句“鸡汤”,希望大家能时刻让自己保持坚强,晚安。

生活不会为谁放慢节奏,我们只能提起精神,抹着泪,踉跄着追上生活的步伐。

Android:是时候掌握WebView与Js的交互技术了相关推荐

  1. Carson带你学Android:你要的WebView与 JS 交互方式都在这里了

    前言 现在很多App里都内置了Web网页(Hybrid App),比如说很多电商平台,淘宝.京东.聚划算等等,如下图 上述功能是由Android的WebView实现的,其中涉及到Android客户端与 ...

  2. Android WebView 与 JS 交互

    2019独角兽企业重金招聘Python工程师标准>>> 在android activity webView的使用,activity中执行html中的js 方法, 和在html 中 调 ...

  3. Android—WebView与JS交互

    Html文件: WebView与JS交互方式: 1. 前提: WebSettings webSettings = webView.getSettings(); // 设置与Js交互的权限 webSet ...

  4. Android之webview与js交互

    对于android初学者应该都了解webView这个组件.之前我也是对其进行了一些简单的了解,但是在一个项目中不得不用webview的时候,发现了webview的强大之处,今天就分享一下使用webvi ...

  5. android webView 与 JS交互方式

    webView 与JS交互 Android调用JS代码的方法有: 通过WebView的loadUrl() 通过WebView的evaluateJavascript() 对于JS调用Android代码的 ...

  6. android webview 监听js,Android webview与js的数据交互

    项目要用到Webview和js交互,查了查以前的项目感觉还是有必要整理下的. 简单描述下项目中用到的地方,比如说在web页需要用到登录的地方点击登录跳转到APP原生登录界面去登录,点击web页的拨打电 ...

  7. Android WebView注入js文件,判断当前HTML有没有某个js然后再注入

    Android WebView注入js文件,判断当前HTML有没有某个js然后再注入 1.注入js代码 判断当前有没有jQuery文件引入,然后再进行注入. 判断依据其实很简单,获取script 的d ...

  8. Android WebView与JS交互入门

    2019独角兽企业重金招聘Python工程师标准>>> 首先在Anndroid代码中对WebView进行初始化 webView = (WebView) findViewById(R. ...

  9. android webview调js方法,Android中WebView与H5的交互,Native与JS方法互调

    项目中经常用到WebView与H5的交互,一个是H5调本地方法,一个是本地调H5方法,在此记录一下. 首先,启用JS支持 //启用js支持 webSettings.setJavaScriptEnabl ...

最新文章

  1. Python到底是什么样的语言? Python和Java比谁更快? TensorFlow的主体是用Python写的吗?
  2. 指挥控制系统中的自然智能和人工智能
  3. 第三届山西省赛1004 一道大水题(scanf)
  4. (0021)iOS 开发之-苹果官方文档
  5. 在MFC的picture控件中如何显示Mat图
  6. 4.4.6 数组也能无锁:AtomicIntegerArray
  7. 解决Pytohn安装第三方库出现read timed out 问题
  8. Springboot 2.0.0单元测试
  9. Hive的使用之脚本文件
  10. (69)Verilog HDL测试激励:时钟激励2
  11. 关于el-form中的rules未生效问题的解决方法
  12. SOPC自定义外设(IP)的地址对齐
  13. Ceilometer的知识总结
  14. 【每日算法Day 80】所有人都会做的入门题,高级解法来了!
  15. Java学习6——基本数据类型及其转换
  16. 史上最强三千六百道脑筋急转弯
  17. Debian下解决subclise插件在启动时报fail to load JavaHL Liberary
  18. dyndns免费动态域名
  19. Android 中关于九宫格图片的那些事
  20. 1T数据到底有多大?

热门文章

  1. pytorch 学习1
  2. 用Python在图片上添加注释信息
  3. 动态分区分配存储管理方式的内存分配回收
  4. mysql navicat 多语句_使用Navicat多对多关系SQL语句在MySQL中实现
  5. openlayers 点线面
  6. 我的世界服务器换披风的网站,我的世界评测_我的世界正版披风怎么换|或_游戏手机游戏-中关村在线...
  7. 奈飞文化手册_《奈飞文化手册》内容提炼分享1
  8. linux安装telnet客户端_Redis 6.0 的客户端缓存是怎么肥事?一文带你了解!
  9. 在WSL下安装MYSQL的实验报告_Linux(wsl)安装docker和mysql主从搭建
  10. teleport 组件的作用_对于组件的可重用性,大佬给出来6个级别的见解,一起过目一下