纸上觉来终觉浅,绝知此事要躬行。 - 陆游/诗人(宋)
正文
一切基于项目WebViewStudy来说明,都是最小单元案例,可作为参考研究,本文从几个方面来讲解:
- 1、Java调用WebView里的js代码(传递参数)
- 2、WebView里的js代码调用Java本地方法(传递参数)
- 3、外部注入js代码
- 4、WebView长按事件
相关JS代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <html> <head> <title>js调用android原生代码</title> <meta http-equiv="Content-Type" content="text/html;charset=gb2312"> <meta id="viewport" name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,minimal-ui"> <script type="text/javascript"> function javacalljs(){ document.getElementById("content").innerHTML += "<br\>java调用了js函数,无参"; } function javacalljswithargs(data){ document.getElementById("content").innerHTML += ("<br\>"+data); } </script> </head> <body> <br/><br/> <li><a onClick="window.injectedObject.startFunction()">点击调用java代码</a></li> <li><a onClick="window.injectedObject.startFunction('我是网页传出来的数据')">点击调用java代码并传递参数</a></li><br/> <div id="content">内容显示</div> </body> </html>
|
Java调用WebView里的js代码(传递参数)
// 告诉WebView启用JavaScript执行。默认的是false。
ws.setJavaScriptEnabled(true);
1、如果点击调用就直接执行就好:
1 2 3 4
| webView.loadUrl("javascript:javacalljs()"); webView.loadUrl("javascript:javacalljswithargs('" + "android传入到网页里的数据,有参" + "')");
|
2、如果是显示后就调用,注意放在html显示完成之后
MyWebViewClient.java
1 2 3 4 5 6 7 8
| @Override public void onPageFinished(WebView view, String url) { webView.loadUrl("javascript:javacalljs()"); webView.loadUrl("javascript:javacalljswithargs('" + "android传入到网页里的数据,有参" + "')"); super.onPageFinished(view, url); }
|
1 2 3 4 5 6 7 8 9 10
| * 4.4以上可用 evaluateJavascript 效率高 */ private void load(String jsCode) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { evaluateJavascript(jsCode, null); } else { loadUrl(jsCode); } }
|
WebView里的js代码调用Java本地方法(传递参数)
这里有一个js点击方法:
1 2
| <li><a onClick="window.injectedObject.startFunction()">点击调用java代码</a></li> <li><a onClick="window.injectedObject.startFunction('我是网页传出来的数据')">点击调用java代码并传递参数</a></li>
|
实现与js交互接口:
1
| webView.addJavascriptInterface(new MyJavascriptInterface(this), "injectedObject");
|
这里的”injectedObject”对应js里的”window.injectedObject.startFunction()”,其中MyJavascriptInterface.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| * Created by jingbin on 2016/11/17. * js通信接口 */ public class MyJavascriptInterface { private Context context; public MyJavascriptInterface(Context context) { this.context = context; } * 前端代码嵌入js: * imageClick 名应和js函数方法名一致 * * @param src 图片的链接 */ @JavascriptInterface public void imageClick(String src) { Log.e("imageClick", "----点击了图片"); Log.e("src", src); } * 前端代码嵌入js * 遍历<li>节点 * * @param type <li>节点下type属性的值 * @param item_pk item_pk属性的值 */ @JavascriptInterface public void textClick(String type, String item_pk) { if (!TextUtils.isEmpty(type) && !TextUtils.isEmpty(item_pk)) { Log.e("textClick", "----点击了文字"); Log.e("type", type); Log.e("item_pk", item_pk); } } * 网页使用的js,方法无参数 */ @JavascriptInterface public void startFunction() { Log.e("startFunction", "----无参"); } * 网页使用的js,方法有参数,且参数名为data * * @param data 网页js里的参数名 */ @JavascriptInterface public void startFunction(String data) { Log.e("startFunction", "----有参" + data); } }
|
且对标里面的两个方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| * 网页使用的js,方法无参数 */ @JavascriptInterface public void startFunction() { Log.e("startFunction", "----无参"); } * 网页使用的js,方法有参数,且参数名为data * * @param data 网页js里的参数名 */ @JavascriptInterface public void startFunction(String data) { Log.e("startFunction", "----有参" + data); }
|
外部注入js代码
有时候我们得到一个网页,这个网页并不是我们订制的,里面没有我们调用的js代码,这时候我们可在前端直接注入js的。
比如 网页里面有图片,我们点击图片想要查看图片和保存图片到本地,这时候网页并没有实现这个js方法供我们调用,但是我们可以注入js代码,来实现这个需求。
在html加载完成之后,我们调用这段js:
1 2 3 4 5 6 7 8
| webView.loadUrl("javascript:(function(){" + "var objs = document.getElementsByTagName(\"img\");" + "for(var i=0;i<objs.length;i++)" + "{" + "objs[i].onclick=function(){window.injectedObject.imageClick(this.getAttribute(\"src\"));}" + "}" + "})()");
|
这时候再看MyJavascriptInterface.java里的imageClick方法:
1 2 3 4 5 6 7 8 9 10 11
| * 前端代码嵌入js: * imageClick 名应和js函数方法名一致 * * @param src 图片的链接 */ @JavascriptInterface public void imageClick(String src) { Log.e("imageClick", "----点击了图片"); Log.e("src", src); }
|
src即为图片链接,可以作为显示和下载用。
WebView长按事件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| webView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { final WebView.HitTestResult hitTestResult = webView.getHitTestResult(); if (hitTestResult.getType() == WebView.HitTestResult.IMAGE_TYPE || hitTestResult.getType() == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) { new AlertDialog.Builder(WebViewActivity.this) .setItems(new String[]{"查看大图", "保存图片到相册"}, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { String picUrl = hitTestResult.getExtra(); Log.e("picUrl", picUrl); switch (which) { case 0: break; case 1: break; default: break; } } }) .show(); return true; } return false; } });
|
参考资料