Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSBridge总结 #11

Open
Cyrilszq opened this issue May 2, 2017 · 0 comments
Open

JSBridge总结 #11

Cyrilszq opened this issue May 2, 2017 · 0 comments

Comments

@Cyrilszq
Copy link
Owner

Cyrilszq commented May 2, 2017

在native调用js方法

Android:

webview.getSettings().setJavaScriptEnabled(true);
// 需要webview加载完成调用
// 格式javascript:jsMethodName
// 相当于在页面控制台(console)直接调用jsMethodName()
webview.loadUrl("javascript:jsFuc()"); // some message

HTML:

<script>
  function jsFuc(){
    alert('some message')
  }
</script>

在js中调用native方法

主要有两种,注入API和拦截URL SCHEME

注入API(addJavascriptInterface)

注入 API 方式的主要原理是,通过 WebView 提供的接口,向 JavaScript 的 Context(window)中注入对象或者方法,让 JavaScript 调用时,直接执行相应的 Native 代码逻辑,达到 JavaScript 调用 Native 的目的。

Android:

class JSInterface {  
    @JavascriptInterface
    public void callNative() {
        // call native method
    }
}
// 相当与在window对象上挂了JSBridge对象
// 通过JSBridge.callNative()调用native方法
webView.addJavascriptInterface(new JSInterface(), "JSBridge");

HTML:

<script>
  JSBridge.callNative() 
</script>

在4.2以前addJavascriptInterface有漏洞,所以4.2以上引入注解@JavascriptInterface来解决,对于4.2一下版本可以使用拦截prompt实现:

Android:

class myClient extends WebChromeClient{
    @Override
    public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
        // 接收到js中的prompt中的参数,根据参数这里可以调用相应的native方法
        Log.d("TAG", message); // ok
        result.confirm();
        return true;
    }
}
webview.setWebChromeClient(new myClient());

HTML:

<script>
  prompt('ok')
</script>

拦截URL SCHEME

拦截 URL SCHEME 的主要流程是:Web 端通过某种方式(例如 iframe.src)发送 URL Scheme 请求,之后 Native 拦截到请求并根据 URL SCHEME(包括所带的参数)进行相关操作。

优点是可以兼容IOS6,所以现在基本可以忽略这种方法了

HTML:

<script>
  let iframe = document.createElement('iframe');
  iframe.src = 'jsbridge://namespace.method?[...args]';
</script>

Android:

webview.setWebViewClient(new WebViewClient() {
  @Override
  public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
      return super.shouldInterceptRequest(view, request);
  }
});

总结

Hybrid中的JSBridge就是这几种,实际生产环境还需要进行封装,定义传参格式等等,但基本原理是不变的。更加详细的内容:移动混合开发中的 JSBridge

关于React Native或Weex中的JSBridge,还是比较复杂的,因为它们都将html页面映射成了原生组件,不在基于webview提供的那几个API。它们是通过JNI,让C++作为一个中间层,实现Java与JS的绑定。这里有几篇详细的文章:Weex SDK Android 源码解析React Native Android版核心层js-bridge实现浅析

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant