android_jsbridge,让你和前端愉快的交互

android_js

前言

做为开发人员都知道,客户端的版本更新对于用户来讲代价是很大的。为了知足客户端可以快速更新迭代的要求,许多app都内嵌入了H5,好比不少电商平台,淘宝、京东、
聚划算等等。这类技术的关键就是在于Android客户与Web前端之间的交互。不少大型项目的接口为了防止Spammer的侵入,都是要求只能由客户端发起请求的。因此本项目
就封装了一个module,实现客户端接收前端的调用,而后由客户端发起Http请求的功能。
复制代码
开始介绍项目以前,先来快速回顾一下Android客户端与Web前端之间交互的几种方式。
复制代码

1. Android调用JS方法

1.1 经过WebView的loadUrl()

android客户端代码:javascript

private void initWebView() {
    WebSettings webSettings = webView.getSettings();
    webSettings.setJavaScriptEnabled(true); // 设置与Js交互的权限
    webSettings.setJavaScriptCanOpenWindowsAutomatically(true); // 设置容许JS弹窗

    webView.loadUrl("file:///android_asset/javascript.html");
    webView.setWebChromeClient(new WebChromeClient() {

        @Override
        public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
            AlertDialog.Builder b = new AlertDialog.Builder(SimpleWebViewActivity.this);
            b.setTitle("Alert");
            b.setMessage(message);
            b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    result.confirm();
                }
            });
            b.setCancelable(false);
            b.create().show();
            return true;
        }
    });
}

private void setListener() {
    btnLoadUrl.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            webView.post(new Runnable() {
                @Override
                public void run() {
                    // 此处的callJS方法名与JS中的function方法名必需要一致
                    webView.loadUrl("javascript:callJS()");
                }
            });
        }
    });
}
复制代码

javascript前端代码:html

<!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>Carson_Ho</title>
        // JS代码
        <script>
            // Android须要调用的方法
           function callJS() {
              alert("Android调用了JS的callJS方法");
           }

        </script>
    </head>
    </html>
复制代码
运行结果如图
复制代码

    android客户端代码:

btnEvaluateJavascript.setOnClickListener(new View.OnClickListener() {

        @TargetApi(19)
        @Override
        public void onClick(final View v) {
            webView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {
                @Override
                public void onReceiveValue(String value) {
                    //此处为 js 返回的结果
                    Log.d(TAG, "value---" + value);
                }
            });
        }
    });
复制代码
运行结果跟上图是同样的。
复制代码
两种交互方式的比较
复制代码
调用方式 优势 缺点 使用场景
使用loadUrl() 方便简洁 效率低;获取返回值麻烦 不须要使用返回值,对性能要求较低
使用evaluateJavascript() 效率高 向下兼容性差(仅Android 4.4以上可用) Android 4.4及以上

1.3 使用建议

// Android版本变量
final int version = Build.VERSION.SDK_INT;
// 由于该方法在 Android 4.4 版本才可以使用,因此使用时需进行版本判断
if (version < 18) {
    webView.loadUrl("javascript:callJS()");
} else {
    webView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {
        @Override
        public void onReceiveValue(String value) {
            //此处为 js 返回的结果
        }
    });
}
复制代码

2. JS调用Android方法

2.1 经过WebView的addJavascriptInterface()进行对象映射

代码再也不贴出,详细代码请参见:代码地址    运行结果以下: 前端

2.2 经过 WebViewClient 的方法shouldOverrideUrlLoading()回调拦截 url

代码再也不贴出,详细代码请参见:代码地址    运行结果以下: java

2.3 经过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt()消息

代码再也不贴出,详细代码请参见:代码地址    运行结果以下: android

2.3.1 onJsAlert()、onJsConfirm()、onJsPrompt()三者之间的比较
方法 做用 返回值
alert() 弹出警告框 没有
confirm() 弹出确认框 两个返回值(true或false)
prompt() 弹出输入框 任意设置返回值
2.3.2 总结
经常使用的拦截是:拦截 JS的输入框(即prompt()方法),由于只有prompt()能够返回任意类型的值,操做最全面方便、更加灵活,
而alert()对话框没有返回值,confirm()对话框只能返回两种状态(肯定 / 取消)两个值。
复制代码

2.4 三种Android Call Js 方式的对比以及使用场景

调用方式 优势 缺点 使用场景
经过WebView的addJavascriptInterface()
进行对象映射
方便简洁 Android 4.2如下存在漏洞问题 Android 4.2以上相对简单的互调场景
经过 WebViewClient 的方法shouldOverrideUrlLoading()
回调拦截 url
不存在漏洞问题 有协议约束,客户端向前端传值繁琐 不须要返回值的互调场景
经过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法
回调拦截JS对话框alert()、confirm()、prompt()消息
不存在漏洞问题 有协议约束 能知足大多数状况下的互调场景

附:WebView的addJavascriptInterface()方法在Android 4.2如下存在的漏洞git

以上都是对基础知识的回顾,下面的才是本项目的解释说明。注意了,如下才是本项目的解释说明!!

先来看一下项目运行的效果图:
复制代码

你们会说,这个不是跟拦截JS的prompt()方法同样么,没错,js和android之间的交互,也无非上面提到的几种方法,这里作的封装采用的是:
js调android:经过WebView的addJavascriptInterface()进行对象映射
android回调js:android 4.4以上采用WebView的evaluateJavascript()方法,android 4.4如下采用loadUrl()方法
复制代码
android端代码:
复制代码

JsBridgeWebView 这是一个继承WebView的类,它里面向JS注入了一个对象供JS调用,JS能够经过这个对象调用Native的方法,调哪一个方法,传哪些参数,彻底由JS决定,方法名必须两端协议,Native经过反射找到对应的方法。传递过来的参数重包含了JS回调方法的方法名,客户端执行完相应的操做以后再去执行JS的方法。github

js代码:
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
        <title>Carson</title>
        <script>
            function callAndroid(){
                // 因为对象映射,因此调用jsCallback对象等于调用Android映射的对象
                var json = "{\"name\": \"zlove\", \"_dscbstub\": \"callback\"}"
                _jsbridge.call("testAsync", json);
             }
             function callback(result) {
                alert("客户端返回的结果是:" + result)
             }
        </script>
</head>
<body>
<!-- 点击按钮则调用callAndroid函数 -->
<button type="button" id="button1" style="font-size:30px" onclick="callAndroid()">Call Android</button>
</body>
</html>
复制代码
var json = "{\"name\": \"zlove\", \"_dscbstub\": \"callback\"}" 
_jsbridge.call("testAsync", json);
_jsbridge表示客户端注入的对象,testAsync是方法名,json是参数,而_dscbstub对应的callback是js的回调方法。
复制代码

end

原本觉得要写不少,事实上其实把基础原理写清楚了,也就这么多😂😂😂。
I hope this will help you!
复制代码

附:源码地址web

相关文章
相关标签/搜索