您的位置:首页 > Web前端 > JavaScript

[置顶] [HyBrid]HyBrid混编初尝:原生和第三方JsBridge的使用

2016-09-29 17:03 411 查看
最近研究HyBrid的两种方式:

一、直接原生WebView

1)初始化WebView:

<span style="white-space:pre">	</span>//启动javascript
webView = (WebView) findViewById(R.id.webView);
//webView.setVerticalScrollbarOverlay(true);
String uri = "file:///android_asset/js_test2.html";
webView.loadUrl(uri);
// 添加客户端支持
webView.setWebChromeClient(new WebChromeClient());
// 设置WebView支持JavaScript
webView.getSettings().setJavaScriptEnabled(true);
注释比较清楚,不多解释。

2)WebView与js通信

原生中代码:

// 调用js中的函数:jsFun(msg)
webView.loadUrl("javascript:jsFun('" + msg + "')");
直接通过Url加载javascript:+方法名

js中对应代码:

//在java中调用此方法
function jsFun(msg){
alert("我是js方法,被java调用,传递过来的参数是:"+msg);
}


如此即可调用在native中调用js代码:效果图如下:



3)js与WebView通信

native中添加:

//  添加js交互接口
webView.addJavascriptInterface(new MyJava(this), "javaObject");
addJavascriptInterface()源码:

* @param object the Java object to inject into this WebView's JavaScript
*               context. Null values are ignored.
* @param name the name used to expose the object in JavaScript
*/
public void addJavascriptInterface(Object object, String name) {
checkThread();
mProvider.addJavascriptInterface(object, name);
}
第一个参数是Object对象:将Object对象注入到WebView的JavaScript的上下文中。

第二个参数name:在JavaScript暴露对象使用的名称。

通俗点讲:也就是用第二个参数名字在js中使用,来引用第一个java对象。

我们这个例子中自定义了一个MyJava对象:

private class MyJava {
private Context mContext;

public MyJava(Context context) {
this.mContext = context;
}

// 在js中调用window.javaObject.javaFun(name),便会触发此方法。
// api17版本以上加上注解
@JavascriptInterface
public void javaFun(String name) {
Toast.makeText(mContext, "我是java方法,被js调用,js传递过来的参数是:" + name,
Toast.LENGTH_LONG).show();
}
}
构造方法直接忽略。这句注释千万不能忽略。

@JavascriptInterface
涉及到4.2以上版本能否使用。4.2之前有个安全漏洞,4.2之后修复的方式,是js调用native的方法,方法上必须通过该注释注明才可以调用。

方法javaFun很简单,不多说,直接看js中如何调用。

js中添加:

function sendInfoToJava(){
//js调用java方法,并传递参数
var value = document.getElementById("name_input").value;
window.javaObject.javaFun(value);
}
通过window.javaObject.javaFun(value)调用native的方法。之前已经解释过javaObject引用MyJava对象。然后通过对象引用方法。

js引用native动画效果如下:



二、JsBridge方法实现HyBrid

一、导入第三方类库:

PS : JsBridge类库地址。

二、Android Studio导入第三方类库说简单简单,说难也难。

查看类库结构:



导入步骤:

1)先复制上述第三方类库到app平级处:如下



2)导入第三方类库:如下图:按顺序:







此处上面的example就不要导入了。一个样例,导入多余,还可能冲突。选择finish。导入第三方完毕。

高兴的太早了。主项目还调用不了这个导入的第三方包。

还需如下设置:





选择之前的命名的第三方类库,ok导入完毕。可以正常使用了。

三、使用JsBridge实现

PS:查阅了好多资料,之后总算是懂了。哎。好好学习,天天向上吧,少年。

通用部分:

1)使用JsBridge的WebView:BridgeWebView

xml:写一个BridgeWebView

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<!-- button 演示Java调用web -->
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:text="button 演示Java调用web"
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>
说明:

样式很简单:上面一个按钮写着:button 演示Java调用web。下面一个第三方自定义webView控件。

第一版资源文件demo.html:(Js看不懂,可以看完下面的描述再看)

<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type">
<title>
js调用java
</title>
</head>
<body>
<a id="show"></a>
<script>

function connectWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge)
} else {
document.addEventListener(
'WebViewJavascriptBridgeReady'
, function() {
callback(WebViewJavascriptBridge)
},
false
);
}
}
connectWebViewJavascriptBridge(function(bridge) {
bridge.init(function(message, responseCallback) {
console.log('JS got a message', message);
responseCallback(data);
});
bridge.registerHandler("functionInJs", function(data, responseCallback) {
document.getElementById("show").innerHTML = ("Native发来的消息是:" + data);
var responseData = "Javascript Says Right back aka!";
responseCallback(responseData);
});
})

</script>
</body>
</html>


2)直入主题:Native发送消息给H5

Acitivity中:通过上面的Native按钮发消息给H5:

Activity初始化JsBridge:

<span style="white-space:pre">	</span>setContentView(R.layout.activity_main);
webView = (BridgeWebView) findViewById(R.id.webView);
webView.loadUrl("file:///android_asset/demo.html");
只需要找到加载H5资源即可。Native点击事件如下:

@Override
public void onClick(View v) {
webView.callHandler("functionInJs", "传递消息给H5", new CallBackFunction() {
@Override
public void onCallBack(String data) {
}
});
}
H5如何能接收呢?如上注册了一个functionInJs,那么应该在H5中对应的写法。

说到这,必须先说说

H5初始化JsBridge:

H5初始化JsBridge第一步:

connectWebViewJavascriptBridge(function(bridge) {
bridge.init(function(message, responseCallback) {
console.log('JS got a message', message);
responseCallback(data);
});
})


H5初始化JsBridge第二步:

function connectWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge)
} else {
document.addEventListener(
'WebViewJavascriptBridgeReady'
, function() {
callback(WebViewJavascriptBridge)
},
false
);
}
}
知道在哪初始化了,那么我就在[H5初始化JsBridge第一步]里面注册H5后如下:

connectWebViewJavascriptBridge(function(bridge) {
bridge.init(function(message, responseCallback) {
console.log('JS got a message', message);
responseCallback(data);
});
bridge.registerHandler("functionInJs", function(data, responseCallback) {
document.getElementById("show").innerHTML = ("Native发来的消息是:" + data);
var responseData = "Javascript Says Right back aka!";
responseCallback(responseData);
});
})
加上这一段代码就对应注册了functionInJs。

看看动图效果图:



3)直入主题:H5发送消息给Native

第二版资源文件demo.html:

<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type">
<title>
js调用java
</title>
</head>
<body>
<input type="button" value="点击1" onclick="go()"/>
<a id="a"></a>
<script>
function go(){ window.WebViewJavascriptBridge.callHandler( "Android", "Hello~", function(responseData){ document.getElementById('a').innerHTML = 'Native给我的数据: ' + responseData; } ); }

function connectWebViewJavascriptBridge(callback) { if (window.WebViewJavascriptBridge) { callback(WebViewJavascriptBridge) } else { document.addEventListener( 'WebViewJavascriptBridgeReady' , function() { callback(WebViewJavascriptBridge) }, false ); } }

connectWebViewJavascriptBridge(function(bridge) { bridge.init(function(message, responseCallback) { console.log('JS got a message', message); responseCallback(data); }); })

</script>
</body>
</html>
说明:比第一版本多了一个点击事件。排除了第一版本的干扰Js代码。(H5初始化JsBridge不变)

既然是H5调用Native:先看Js的点击事件代码:

function go(){
window.WebViewJavascriptBridge.callHandler(
"Android",
"Hello~",
function(responseData){
document.getElementById('a').innerHTML = 'Native给我的数据: ' + responseData;
}
);
}
三个参数分别是:第一个参数:注册了一个Android。第二个参数:发送的消息内容是Hello~。第三个参数是一个回调。调用成功后,由Native返回responseData。

然后Native对应注册Android:

webView.registerHandler("Android", new BridgeHandler() {
@Override
public void handler(String s, CallBackFunction callBackFunction) {
Toast.makeText(MainActivity.this, "H5给我的数据:" + s, Toast.LENGTH_SHORT).show();
callBackFunction.onCallBack("fuck!");
}
});
这样子,对应注册完毕。

看个动图效果图:点击1被点击后,先弹出Native的Toast,然后回调了H5的内容文本。



正常来说,讲到这儿,应该是讲完了。但是这个第三方还自带懒人功能:Native调用H5:不注册参数。按照我们之前的例子来说就是不设置第一个参数functionInJs。反之,H5调用Native:不注册参数也可以调用默认的Native功能。

4)Native默认设置:H5发送消息给Native。

写一个类继承默认处理类DefaultHandler

class MDefaultHandler extends DefaultHandler{
@Override
public void handler(String data, CallBackFunction function) {
super.handler(data, function);
Log.d(TAG,data);
Toast.makeText(MainActivity.this,data,Toast.LENGTH_SHORT).show();
}
}


然后对WebView设置:

webView.setDefaultHandler(new MDefaultHandler());
Js调用的时候如何调用?

直接上demo.html:

<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type">
<title>
js调用java
</title>
</head>
<body>
<input type="button" value="点击1" onclick="go()"/>
<a id="a"></a>
<script>
function go(){
window.WebViewJavascriptBridge.send( "被传递的Data" , function(responseData) { document.getElementById("a").innerHTML = "H5默认调用Native" + responseData } );
}

function connectWebViewJavascriptBridge(callback) { if (window.WebViewJavascriptBridge) { callback(WebViewJavascriptBridge) } else { document.addEventListener( 'WebViewJavascriptBridgeReady' , function() { callback(WebViewJavascriptBridge) }, false ); } }

connectWebViewJavascriptBridge(function(bridge) { bridge.init(function(message, responseCallback) { console.log('JS got a message', message); responseCallback(data); }); })

</script>
</body>
</html>
可见只是这儿有所修改:

window.WebViewJavascriptBridge.send(
"被传递的Data"
, function(responseData) {
document.getElementById("a").innerHTML = "H5默认调用Native" + responseData
}
);
改变:只有两个参数了。方法名变成了send。

看看动画效果图:



5)Js默认设置:Native发送消息给H5。

看看Js初始化第一步:

connectWebViewJavascriptBridge(function(bridge) {
bridge.init(function(message, responseCallback) {
console.log('JS got a message', message);
responseCallback(data);
});
})


此处的message其实就是默认的发来的消息。

Native发送默认消息方式非常简单:点击事件里面调用一下即可:

@Override
public void onClick(View v) {
webView.send("hello来自Native的默认消息");
}
为了方便验证:将Js初始化第一步改成如下:

connectWebViewJavascriptBridge(function(bridge) {
bridge.init(function(message, responseCallback) {
document.getElementById("a").innerHTML = "来自Native的:" + message;
responseCallback(data);
});
})
也就是在id等于a的文本处展示。

动图效果图如下:



Over~打算再写一章关于JsBridge的原理,看看我能不能读懂大神的源码吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: