Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

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

$
0
0

最近研究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的原理,看看我能不能读懂大神的源码吧。

作者:haibo_bear 发表于2016/9/29 17:03:45 原文链接
阅读:186 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>