Files
knowledge-kit/第一部分 iOS/1.46.md
2020-02-25 17:35:10 +08:00

2.3 KiB
Raw Blame History

Hybrid

Android 端如何与 JS 通信2种方法

  • webview.loadUrl()
  • Webview.evaluateJavascript()

2者区别

  1. loadUrl() 会刷新页面evaluateJavascript() 则不会刷新页面,效率高
  2. loadUrl() 得不到 JS 的返回值evaluateJavascrip() 则可以获取返回值
  3. evaluateJavascrip() 在 Android 4.4 之后才可以使用

注意Android 可以直接调用 JS 的 alert() 方法是因为 alert 方法直接挂载在 window 对象上。但是 Native 与 JS 可能不止一个方法、多个方法多个属性去访问,这样都直接挂载在 window 对象上不是明智之举。因为后期维护很不方便。所以我们在 Native 和 JS 之间会设置一个桥接对象像一个中间层一样让2端互调。

Android 需要在页面加载完,也就是 webview 的 onPageFinished 方法中写调用逻辑,否则不会执行

webView.loadUrl("javascript:callJsFunction('soloname')")
webView.evaluateJavascript("javascript:callJsFunction('soloname')"

JS 如何与 Android 通信

  • 通过 Webview 的 addJavascriptInterface() 进行对象映射
  • 通过 WebviewClient 的 shouldOverrideUrlLoading() 方法回调拦截 Url
  • 通过 webChromeClient 的 onJsAlert()、onJSPrompt() 方法回调拦截 JS 对话框 alert()、confirm()、prompt() 等消息

第一种最简洁,但是在 Android 4.2 以下存在漏洞。

实验Android webview 上跑一个网页,点击网页的按钮,让 Native 弹出一个字符串。

methods: {
  showAndroidToast() {
    $App.showToast("哈哈我是js调用的")
  }
}
public class JsJavaBridge {

    private Activity activity;
    private WebView webView;

    public JsJavaBridge(Activity activity, WebView webView) {
        this.activity = activity;
        this.webView = webView;
    }

    @JavascriptInterface
    public void onFinishActivity() {
        activity.finish();
    }

    @JavascriptInterface
    public void showToast(String msg) {
        ToastUtils.show(msg);
    }
}

然后通过 webview 设置 Android 类与 JS 代码的映射

webView.addJavascriptInterface(new JsJavaBridge(this, tbsWebView), "$App");

这里将类 JsJavaBridge 在 JS 中映射为了 $App所以在 Vue 中可以这样调用 $App.showToast("哈哈我是js调用的")