如何实现nodejs调用java接口,将结果返回

今天看啥 热点:
Android 利用WebViewJavascriptBridge 实现js和java的交互(一),androidjsbridge
& & & 此文出自:http://blog.csdn.net/sk/article/details/ ,skay 博客
& & 按安卓开发目前现状来说,开发者大部分时间还是花在UI的屏幕适配上,使用原生控件开发成本已不是那么理想,鉴于很多项目和ios基于一致的ui界面,至使安卓UI开发成本花费更大的代价,因此目前结合Html5和原生控件是解决UI适配的一种很好的选择,处于APP性能也会用java和native层进行结合。不管是哪种结合,其实原理都差不多,只要按照它的协议来,是很容易的,今天我们仅对于Html和Java层结合,学习下一个新的开源项目--WebViewJavascriptBridge。
& &一 什么是webViewjavascripBridge?
& & & &WebViewJavascriptBridge是移动UIView和Html交互通信的桥梁,用作者的话来说就是实现java(ios为oc)和js的互相调用的桥梁。替代了WebView的自带的JavascriptInterface的接口,使得我们的开发更加灵活和安全。
&二 为什么要用webViewjavascripBridge?
& & 对于安卓开发有一段时间的人来说,知道安卓4.4以前谷歌的webview存在安全漏洞,网站可以通过js注入就可以随便拿到客户端的重要信息,甚至轻而易举的调用本地代码进行流氓行为,谷歌后来发现有此漏洞后,增加了防御措施,如果要是js调用本地代码,开发者必须在代码申明JavascriptInterface,
& &列如在4.0之前我们要使得webView加载js只需如下代码:
&&mWebView.addJavascriptInterface(new JsToJava(), &myjsfunction&);
& & &4.4之后调用需要在调用方法加入加入@JavascriptInterface注解,如果代码无此申明,那么也就无法使得js生效,也就是说这样就可以避免恶意网页利用js对安卓客户端的窃取和攻击。
& & & 但是即使这样,我们很多时候需要在js记载本地代码的时候,要做一些判断和限制,或者有可能也会做些过滤和对用户友好提示,因此JavascriptInterface也就无法满足我们的需求了,特此有大神就写出了WebViewJavascriptBridge框架。
三 怎么使用webViewjavascripBridge
& & & 1 将jsBridge.jar引入到我们的工程
& & & & &此jar,或者jar源码我们可以到gitHub上下载。
& & & 2 WebView包需使用以上包的webView
& & & & & & & Layout中使用第三方view,
& & & & & & & EG:
& & & & & & &&?xml version=&1.0& encoding=&utf-8&?&
&LinearLayout xmlns:android=&/apk/res/android&
android:layout_width=&match_parent&
android:layout_height=&match_parent&
android:orientation=&vertical& &
&!-- button 演示Java调用web --&
android:id=&@+id/button&
android:layout_width=&match_parent&
android:text=&@string/button_name&
android:layout_height=&48dp&
&!-- webview 演示web调用Java --&
&com.github.lzyzsd.jsbridge.BridgeWebView
android:id=&@+id/webView&
android:layout_width=&match_parent&
android:layout_height=&match_parent& &
&/com.github.lzyzsd.jsbridge.BridgeWebView&
&/LinearLayout&
& 3 Java代码
& & &&public class MainActivity extends Activity implements OnClickListener {
private final String TAG = &MainActivity&;
BridgeWebView webV
int RESULT_CODE = 0;
ValueCallback&Uri& mUploadM
static class Location {
static class User {
String testS
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = (BridgeWebView) findViewById(R.id.webView);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(this);
webView.setDefaultHandler(new DefaultHandler());
webView.setWebChromeClient(new WebChromeClient() {
@SuppressWarnings(&unused&)
public void openFileChooser(ValueCallback&Uri& uploadMsg, String AcceptType, String capture) {
this.openFileChooser(uploadMsg);
@SuppressWarnings(&unused&)
public void openFileChooser(ValueCallback&Uri& uploadMsg, String AcceptType) {
this.openFileChooser(uploadMsg);
public void openFileChooser(ValueCallback&Uri& uploadMsg) {
mUploadMessage = uploadM
pickFile();
//加载本地网页
//webView.loadUrl(&file:///android_asset/demo.html&);
//加载服务器网页
webView.loadUrl(&&);
//必须和js同名函数,注册具体执行函数,类似java实现类。
webView.registerHandler(&submitFromWeb&, new BridgeHandler() {
public void handler(String data, CallBackFunction function) {
String str =&这是html返回给java的数据:& +
// 例如你可以对原始数据进行处理
makeText(MainActivity.this, str, LENGTH_SHORT).show();
Log.i(TAG, &handler = submitFromWeb, data from web = & + data);
function.onCallBack( str + &,Java经过处理后截取了一部分:&+ str.substring(0,5));
//模拟用户获取本地位置
User user = new User();
Location location = new Location();
location.address = &上海&;
user.location =
user.name = &Bruce&;
webView.callHandler(&functionInJs&, new Gson().toJson(user), new CallBackFunction() {
public void onCallBack(String data) {
makeText(MainActivity.this, &网页在获取你的位置&, LENGTH_SHORT).show();
webView.send(&hello&);
public void pickFile() {
Intent chooserIntent = new Intent(Intent.ACTION_GET_CONTENT);
chooserIntent.setType(&image/*&);
startActivityForResult(chooserIntent, RESULT_CODE);
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == RESULT_CODE) {
if (null == mUploadMessage){
Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData();
mUploadMessage.onReceiveValue(result);
mUploadMessage =
public void onClick(View v) {
if (button.equals(v)) {
webView.callHandler(&functionInJs&, &data from Java&, new CallBackFunction() {
public void onCallBack(String data) {
// TODO Auto-generated method stub
Log.i(TAG, &reponse data from js & + data);
& & & 通过实例化webView,用法和安卓原生的view没多大区别,设置WebChromClient, 设置加载的html(同样支持网络和本地文件),接着我们需要给web注册和html端约定好的js方法名。代码列举的submitFromweb和js的执行的方法名一致,玩过NDK的JNI调用的朋友也知道必须和c代码之间有个约定,其实js桥和jni有点类似,
通过注册handler来实现回调,Java代码中通过js返回的数据,进行处理后在调用function.onCallback返回给js.这里不做过多解释
//必须和js同名函数,注册具体执行函数,类似java实现类。
webView.registerHandler(&submitFromWeb&, new BridgeHandler() {
public void handler(String data, CallBackFunction function) {
String str =&这是html返回给java的数据:& +
// 例如你可以对原始数据进行处理
makeText(MainActivity.this, str, LENGTH_SHORT).show();
Log.i(TAG, &handler = submitFromWeb, data from web = & + data);
function.onCallBack( str + &,Java经过处理后截取了一部分:&+ str.substring(0,5));
& & &如果是webview刚开始就执行一段Java代码 ,可以通过webView.CallHandler()来实现 。当然我们注册的方法也要和js里面的方法名一致。
& & && webView.callHandler(&functionInJs&, new Gson().toJson(user), new CallBackFunction() {
public void onCallBack(String data) {
makeText(MainActivity.this, &网页在获取你的位置&, LENGTH_SHORT).show();
& 3 Html和js实现
& & & & &html代码如下,效果图
& &&&html&
&meta content=&text/ charset=utf-8& http-equiv=&content-type&&
js调用java
&xmp id=&show&&
&xmp id=&init&&
&input type=&text& id=&text1& value=&用户名(username)& /&
&input type=&text& id=&text2& value=&password& /&
&input type=&button& id=&enter& value=&发消息给Native& onclick=&testClick();&
&input type=&button& id=&enter1& value=&调用Native方法& onclick=&testClick1();&
&input type=&button& id=&enter2& value=&显示html& onclick=&testDiv();& /&
&input type=&file& value=&打开文件&
& && &script&
function testDiv() {
document.getElementById(&show&).innerHTML = document.getElementsByTagName(&html&)[0].innerHTML;
function testClick() {
var str1 = document.getElementById(&text1&).
var str2 = document.getElementById(&text2&).
//发送消息给java代码
var data = &name=& + str1 + &,pass=& + str2;
window.WebViewJavascriptBridge.send(
, function(responseData) {
document.getElementById(&show&).innerHTML = &repsonseData from java, data = & +responseData
function testClick1() {
var str1 = document.getElementById(&text1&).
var str2 = document.getElementById(&text2&).
//调用本地java方法
window.WebViewJavascriptBridge.callHandler(
'submitFromWeb'
, {'param': str1}
, function(responseData) {
document.getElementById(&show&).innerHTML = &send get responseData from java, data = & + responseData
function bridgeLog(logContent) {
document.getElementById(&show&).innerHTML = logC
}//注册事件监听
function connectWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge)
document.addEventListener(
'WebViewJavascriptBridgeReady'
, function() {
callback(WebViewJavascriptBridge)
//注册回调函数,初始化函数
connectWebViewJavascriptBridge(function(bridge) {
bridge.init(function(message, responseCallback) {
console.log('JS got a message', message);
var data = {
'Javascript Responds': 'Wee!'
console.log('JS responding with', data);
responseCallback(data);
bridge.registerHandler(&functionInJs&, function(data, responseCallback) {
document.getElementById(&show&).innerHTML = (&data from Java: = & + data);
var responseData = &Javascript Says Right back aka!&;
responseCallback(responseData);
& & & 这段代码不难理解,我们对上面的id为enter的Button注册了一个点击事件,点击后执行以下testClick()方法,依次类推,其他Button注册事件相同,
& & &当点击“发消息给Native”的按钮时,Js通过webWiew的jsBridage.send()发送一条数据给java层(密码和用户名),同时在此用function()来执行应java层回调函数的。此demo中是把java返回的数据插入到&show&的div里面去。
testClick1():此方法中调用callHandler来调用Java代码的submitFromweb同名函数,可以结合上面的Activty的代码理解下,此函数调用我们已在java注册实现好的
//必须和js同名函数,注册具体执行函数,类似java实现类。
webView.registerHandler(&submitFromWeb&, new BridgeHandler() {
public void handler(String data, CallBackFunction function) {
String str =&这是html返回给java的数据:& +
// 例如你可以对原始数据进行处理
makeText(MainActivity.this, str, LENGTH_SHORT).show();
Log.i(TAG, &handler = submitFromWeb, data from web = & + data);
function.onCallBack( str + &,Java经过处理后截取了一部分:&+ str.substring(0,5));
& & &java注册Js函数如上面列子 ,那么在js中注册方法来注册呢,
& & 在js中我们同样可以直接注册一个回调函数,通过&bridge.registerHandler()来注册,接着调用&responseCallback(responseData)来返回数据给java代码的同名函数。f
也可以直接调用init()来指定网页首次加载上面注册java代码。
connectWebViewJavascriptBridge(function(bridge) {
bridge.init(function(message, responseCallback) {
console.log('JS got a message', message);
var data = {
'Javascript Responds': 'Wee!'
console.log('JS responding with', data);
responseCallback(data);
bridge.registerHandler(&functionInJs&, function(data, responseCallback) {
document.getElementById(&show&).innerHTML = (&data from Java: = & + data);
var responseData = &Javascript Says Right back aka!&;
responseCallback(responseData);
& & &通过以上的代码示例,不难发现此框架的优雅和简便,对js和java双方来说,如果html中的js需要调用java代码,而java代码没做任何实现,那么这个js也是无效的,反之java代码注册的回调函数,没在js里去实现,那么Java也无法获取js远程数据,由此可见此,此通信是双方的,必须由双发来约定,这样就避免了安卓之前存在js注入漏洞,也很大的提高了安全性,也可以保证我们的网页数据不被第三方的APP获取,怎么说呢,比如你的项目某一html界面,被安卓浏览器或者其他第三方App恶意加载你们的网站或网页,那么它的java代码调用你的js函数,比如由你的Js事先注册或者实现,不然跟本无法调用。这样就保证了这个html的唯一性,第三方可以加载预览你的网页,但是第三方java不能和你的js交互通信。同样加载第三方的网页时候,我们可以对第三方网页进行一些行为的过滤,进而对用户进行友好提示。
& & 以上代码只是此开源框架一部分功能,还有很多的功能需要我们去挖掘,以后再给大家解剖下此开源项目的内部实现。欢迎阅读
项目开源地址:/lzyzsd/JsBridge
版权声明:本文为博主原创文章,请尊重原创,转载请标明地址。
暂无相关文章
相关搜索:
相关阅读:
相关频道:
Android教程最近更新博客分类:
其实webview加载资源的速度并不慢,但是如果资源多了,当然就很慢。图片、 css 、 js 、 html 这些资源每个大概需要 10-200ms ,一般都是 30ms 就 ok 了。不过webview是必须等到全部资源都完成加载,才会进行渲染的,所以加载的速度很重要!从Google上我们了解到,webview 加载页面的顺序是:先加载 html ,然后从里面解析出 css 、 js 文件和页面上的图片资源进行加载。如果 webkit 的缓存里面有,就不加载。加载完这些资源之后,就进行 css 的渲染和 js 的执行。 Css 的渲染一般不需要很长时间,几十毫秒就 ok 。关键是 js 的执行,如果用了 jQuery ,则执行起来需要 5-6 秒。而在这段时间,如果不在 webview 里设置背景,网页部分是白色的,很难看。这是一个很糟糕的用户体验。所以如果用网页布局程序,最好别用那些庞大的 js 框架。最好使用原生的js写业务脚本,以提升加载速度,改善用户体验。
Android 的 webview 是基于 webkit 内核的,webview 中集成了js与java互调的接口函数,通过addJavascriptInterface方法,可以将Java的类注册进webkit,给网页上的js进行调用,而且还可以通过loadUrl方法是给webkit传递一个uri,供浏览器来进行解析,实现Java和js交互。
要想运行网页上的js脚本,webview必须设置支持Javascript
mWebview.getSettings().setJavaScriptEnabled(true);
然后是设置webview要加载的网页:
web的网页:webView.loadUrl("");
本地的网页:webView.loadUrl("file:///android_asset/XX.html");
//本地的存放在:assets文件夹中
webview做完基本的初始化后我们还要要给它,加进一个回调的代理类JavaScriptInterface,并给它一个调用的名称:ncp
mWebView.addJavascriptInterface(new JavaScriptInterface(), "ncp");
JavaScriptInterface可以是一个普通的Java类,类实现的方法,均可被js回调:
final class JavaScriptInterface {
public int callOnJs() {
return 1000;
public void callOnJs2(String mode) {
Java要调用js的方法,只需知道js的方法名称即可:
mWebView.loadUrl("javascript:onSaveCallback()");
js 这边就更简单:
&script type="text/javascript"&
window.onload = function(){
document.getElementById('btn_1').addEventListener('click', onBtnClick, false);
var _int_value = window.ncp.callOnJs();
alert("get int from java:" + _int_value );
function onBtnClick() {
window.ncp.callOnJs2("click");
Java和js交互有以下一些特点:
1.Java 调用 js 里面的函数,速度并不令人满意,大概一次一两百毫秒吧,如果要做交互性很强的事情,这种速度会让人疯掉的。而反过来就不一样了, js 去调 java 的方法,速度很快,基本上 40-50 毫秒一次。所以尽量用 js 调用 java 方法,而不是 java 去调用 js 函数。
2.Java 调用 js 的函数,没有返回值,而 Js 调用 java 方法,可以有返回值。返回值可以是基本类型、字符串,也可以是对象。如果是字符串,有个很讨厌的问题,第 3 点我会讲的。如果是对象,这个对象会被转换为 js 的对象,直接可以访问里面的方法。但是我不推荐 java 返回给 js 的是对象,除非是必须。因为 js 收到 java 返回的对象,会产生一些交换对象,而如果这些对象的数量增加到了 500 或 600 以上,程序就会出问题。所以尽量返回基本数据类型或者字符串。
3.Js 调用 Java 的方法,返回值如果是字符串,你会发现这个字符串是 native 的,不能对它进行一些修改操作,比如想对它 substr ,取不到。怎么解决呢?转成 locale 的。使用 toLocaleString() 函数就可以了。不过这个函数的速度并不快,转化的字符串如果很多,将会很耗费时间。
本文由编辑发布,转载请注明出处,谢谢。
浏览 25927
zhiweiofli
浏览: 411481 次
来自: 广州
而且fragment调用back也有不需要finish的时候呢 ...
我这里就是拦截的,但是还是报了这个
IT之冕 写道 我的方法是注释掉super.onBackPre ...
上线毛啊,Bad request了
不错 !!!!!!!!!!!!!!博客分类:
phonegap使用的java与js互相调用的原理。phonegap实现的模型刚也说了,有同步和异步两种。js实现的api,所以是js先会调用java代码,然后再返回给js。对于同步的而言,就是js调用java,然后java返回一个结果作为返回值。对于异步的而言,可能js掉了很多java代码,但是立即返回,然后java代码执行结束后再回调js代码,这里就涉及到js调java,然后java再调用js。
对于js调用java:
js调用java的入口是通过在js中调用prompt方法,这很奇怪吧,这个方法本来是让浏览器弹出个输入框的。我当初找了好久也没发现phonegap到底怎么搞得的让js调用java的代码,后来看到一会觉得该是这个方法,但是这是一个浏览器的客户端自己的东西,而且怪异的是浏览器并没有弹出输入框,后来终于发现。
在DroidGap.java中有个hack,重载了WebviewClient的onJsPrompt方法,然后执行了自己的逻辑。 也就是js调用prompt的时候,java端浏览器代码接受到这个,然后在响应的处理函数中根据传过来的参数,实现了一些特别的逻辑。可以从这个方法的注释上看出一二。
private LinkedL
服务器保存要回调的js的代码,供js客户端取回,这里java端是服务器端,js端是客户端,服务器端不可能请求客户端做啥,是b/s模型,所以phonegap实现了两种服务模型,一种是轮询,一种是XHR异步回调,也就是Ajax的模型。src/com/phonegap/CallbackServer.java是回调服务器的代码所在处。从类的注释中可以看到。
This class provides a way for Java to run JavaScript in the web page that has loaded PhoneGap. The CallbackServer class implements an XHR server and a polling server with a list of JavaScript statements that are to be executed on the web page.
CallbackServer提供的这两种模型,一种是XHR,一种是轮询,轮询很简单了,callbackserver服务器端,有一个保存回调js的列表,前面所说,然后每隔一段时间客户端的js会询问一次服务器,是否有需要回调的js,如果有则调用,然后每隔一段时再查询一次服务器。而基于XHR的,其实这个就是ajax用的机制了,js发起一个异步请求,然后服务器会在返回数据之前保持住这个连接,当返回数据就位后,服务器给请求客户端返回数据,然后关闭连接。然后客户端接受并且处理。
刚说了服务器端的代码实现,现在来看一下客户端js的相关代码。
PhoneGap.JSCallback = function() { ... xmlhttp.open("GET", "http://127.0.0.1:"+PhoneGap.JSCallbackPort+"/"+PhoneGap.JSCallbackToken , true); xmlhttp.send(); }
这个是XHR模型的代码,客户端js使用xhr请求服务器来获取js代码,进行回调。
PhoneGap.JSCallbackPolling = function() { ... var msg = prompt("", "gap_poll:"); if (msg) { setTimeout(function() { try { var t = eval_r(""+msg); } catch (e) { console.log("JSCallbackPolling: Message from Server: " + msg); console.log("JSCallbackPolling Error: "+e); } }, 1); setTimeout(PhoneGap.JSCallbackPolling, 1); } else { setTimeout(PhoneGap.JSCallbackPolling, PhoneGap.JSCallbackPollingPeriod); } }
这个是轮询方式的,可以看到客户端每隔PhoneGap.JSCallbackPollingPeriod段时间,就请求一次服务器(通过prompt("", "gap_poll:");)。
chriszeng87
浏览: 337650 次
来自: 北京
这个目录下没有找到此文件
哥们写东西可真乱啊
这是自己能看懂还是让别人能看得懂,您就不能把版面稍微整理一下吗 ...
string2020 写道git clone --bare表示 ...
git clone --bare表示裸仓请问楼主,什么时候需要 ...Java_爬虫,如何抓取Js动态生成数据的页面?【java吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:651,559贴子:
Java_爬虫,如何抓取Js动态生成数据的页面?收藏
很多网站是用js或Jquery 生成数据的,到后台获取到数据以后,用 document.write()或者(&#id&).html=&& 的方式 写到页面中,这个时候用浏览器查看源码是看不到数据的。HttpClient是不行的,看网上说HtmlUnit, 可以获取后台js加载完后的完整页面,但是我按照文章上说的 写了 ,都不好使。String url = &&;try {
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_10);
//设置webClient的相关参数
webClient.getOptions().setJavaScriptEnabled(true);
webClient.getOptions().setCssEnabled(false);
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
//webClient.getOptions().setTimeout(50000);
webClient.getOptions().setThrowExceptionOnScriptError(false);
//模拟浏览器打开一个目标网址
HtmlPage rootPage = webClient.getPage(url);
System.out.println(&为了获取js执行的数据 线程开始沉睡等待&);
Thread.sleep(3000);//主要是这个线程的等待 因为js加载也是需要时间的
System.out.println(&线程结束沉睡&);
String html = rootPage.asText();
System.out.println(html);} catch (Exception e) {}其实这段代码不好使。求解答,其中典型的就是这个链接的页面,怎么能在java程序中获取其中的数据?
2017java学习来上市公司博为峰学java,入学即签就业协议,不就业不收费,查看java课程!java好学吗?java课程来博为峰学,java工程师就业年薪十几万!
我7 级都要验证码。。。。
htmlUnit是不行的,我试过试试这个,但是这个我没有尝试成功,不知道行不行
换个思路,你可以找到这个页面获取信息的出处地址:其中date是动态的,看js文件:var timstamp=(new Date()).valueOf();var url = ctx + &/main/pro!lrprolist.do?date=&+这样在java中实现获取date,之后访问地址。。。。。
怎么搞???
——From Nokia Lumia1520 大有可言 Windows Phone 8.1
直接URLConnection.open(&Servlet的地址+参数&);然后可以得到JSON数据
我勒个去,怎么代码一直被吞,截个图算了
暂时没有什么好办法,即便goolge 的爬虫,也只能执行少量的js脚本,抓取动态网页也很难
这个是可以用的!就是加载的时候会很慢
楼主问题可否解决,能否说下解决方案
NIIT拥有30年java,小班面授课,1对1辅导,政府扶持+保障(企业定制99%任职),毕业学员告诉你,选择NIIT 任职入职so easy.
3楼提的倒是可以一试
楼主解决没有,,,求支招啊!!!!
可以用selenium,但是因为用到浏览器内核去解析js,所以肯定会很慢,我到现在也没找到解决方案
请问怎么做的?我也遇到了相同的问题
解析的数据,也应该是有数据源的。你可以直接抓数据源,比如一些json数据,或许也可以避开js
楼主找到方法没
卧槽。。我前段时间在抓验证码的时候就是遇到这个问题。。。原来要这么抓动态资源。。收藏一个
登录百度帐号推荐应用

我要回帖

更多关于 java 调用js 的文章

 

随机推荐