这个问题我之前有整理过博客,优化Hybrid app的原生支持

最近在开发中有和同事讨论过这个问题。 好像还挺能唬人的

其实是很简单的问题,这里也整理一下。

场景是原生需要给H5提供一些额外的支持,比如说打开一个新的APP,比如打开原生APP中的某些情况,比如说帮忙旋转一下屏幕。

H5有几种方式可以和原生沟通的:

  1. 打开自定义协议链接

原理很简单,就是浏览器拦截一下请求,看看协议是不是我们沟通好的协议,如果是的话,就做特定的行为,这种方式额外的开销很小。
注意点就是H5要先知道是不是自己的浏览器。。。

  1. 使用原生提供的函数

我以前的文章也写过…

//android:
webview.addJavascriptInterface(new JsObject(), "nativeJava");
public class JsObject implements nativeJava{
    @JavascriptInterface
    public void clearHistory(){
        //let it empty
    }
}
 
//javascript
window.nativeJava.clearHistory()
  1. JsBridge

但是注入这种方式有危险。所以为了绕过这个漏洞,可以用alert 来做

已知的情况是原生可以处理 onJsAlert 的信息。

alert(JSON.stringify({
    'method': method,
    'arg1': arg1,
    'arg2': arg2
}));

注意点:
每一行JS都要有分号
每一行JS都要有分号
每一行JS都要有分号
每一行JS都要有分号

// mWebview.setWebChromeClient(new YeshenChromeClient());
private final class YeshenChromeClient extends WebChromeClient {

    public void onReceivedTitle(WebView view, String title) {
        mDelegate.onReceivedTitle(view, title);
    }

    @Override
    public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
        // Handling js-bridge API
        if (mDelegate.dispatch(message)) {
            result.confirm();
        } else {
            result.cancel();
        }
        return true;
    }

    @Override
    public void onProgressChanged(WebView view, int newProgress) {
        if (view != null) {
            if (mInjectedProgress.checkAndUpdate(view, newProgress)) {
                // Inject js-sdk from assert
                runJs(mDelegate.readJsContent(getContext()));
            }
            super.onProgressChanged(view, newProgress);
        }
    }
}

那么就简单了,可以这样 干净 的调用~

  • 在页面加载之前,注入一段代码,把原生的api挂载到window对象下。
  • 在api中调用alert,把参数回传给原生。
  • H5判断这个方法存不存在,存在就调用

玩~

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐