H5 与Native的交互方案

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了H5 与Native的交互方案相关的知识,希望对你有一定的参考价值。

参考技术A App里基本都少不了H5页面,因此JS与Native之间的通信不可避免,最近留意了一些方案,做下总结。

ios有两种webview,ios8以上推出了WKWebView,低于ios8用的是UIWebView,WKWebView性能上优于UIWebView

Native调用javascript语言,是通过UIWebView组件的stringByEvaluatingJavaScriptFromString方法来实现的,该方法返回js脚本的执行结果。

双方只需要约定好JS端函数名称及参数

JS调用Native,并没有现成的API可以使用,需要借助iframe来实现。原理是在UIWebView内发起的所有网络请求,都可以通过delegate函数在Native层得到通知。所以只需要劫持该UIWebView内的所有请求(通常是这样的格式: jsbridge://methodName?param1=value1¶m2=value2 ),然后在UIWebView的delegate函数中,只要发现是jsbridge://开头的地址,就不进行内容的加载,转而执行相应的调用逻辑:

android里是使用webview的loadUrl进行调用的

有两种比较好的方式:

JS端可以直接调用:alert(AndroidJS.getUserData()) //UserDate

基于 callHandler 和 registerHandler的方式,比较干净

1、 Web 与 App 数据交互原理和实现
2、 WK 与 JS 的那些事
3、 H5 与 Native 交互之 JSBridge 技术
4、 WebView 开车指南之最全实用案例

Android WebView开发:WebView与Native交互

一、Android WebView开发(一):基础应用
二、Android WebView开发(二):WebView与Native交互
三、Android WebView开发(三):WebView性能优化
四、Android WebView开发(四):WebView独立进程解决方案
五、Android WebView开发(五):自定义WebView工具栏

附GitHub源码:WebViewExplore


一、JS调用Native的三种方式:

1、通过WebView的addJavascriptInterface进行对象映射:

需要注意的是这种调用方式,如果你的 minSdkVersion <=16那么需要考虑到4.2之前的漏洞问题。

mWebView.addJavascriptInterface(new JsCallAndroidInterface(), "JSCallBackInterface");
    /**
     * JS调用android原生方法1:
     *
     * 通过WebView的addJavascriptInterface()进行对象映射
     */
    private class JsCallAndroidInterface 

        /**
         *@JavascriptInterface注解方法.
         * js端调用,4.2以后安全;4.2以前,当JS拿到Android这个对象后,
         * 就可以调用这个Android对象中所有的方法,包括系统类(java.lang.Runtime 类)
         * 从而进行任意代码执行。
         * @param msg
         */
        @JavascriptInterface
        public void callback(String msg) 
            ToastUtil.showToast(APIWebViewActivity.this, "JS方法回调到web了 :" + msg);
        
    

2、通过WebViewClient shouldOverrideUrlLoading方法回调拦截url:

与上一篇讲到的url重定向类似,可在此做url的拦截,已达到针对性的调用native方法的目的。

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) 
    if (resolveShouldLoadLogic(url)) 
        return true;
    
    return super.shouldOverrideUrlLoading(view, url);

    /**
     * JS调用android原生方法2:
     *
     * 通过WebViewClient shouldOverrideUrlLoading方法回调拦截url
     *
     * 根据协议的参数,判断是否是所需要的url:
     * 一般根据scheme(协议格式),authority(协议名)来判读
     *
     * @param url
     * @return
     */
    private boolean resolveShouldLoadLogic(String url) 
        Uri uri = Uri.parse(url);
        if (uri.getScheme().equals("js")) 
            if (uri.getAuthority().equals("Authority")) 
                ToastUtil.showToast(APIWebViewActivity.this, "方法2");
            
            return true;
        
        return false;
    

3、通过WebChromeClient的 onJsPrompt()等方法 ,回调拦截JS对话框prompt()等:

        /**
         * 是否支持页面中的js输入弹出框
         *
         * @param view
         * @param url
         * @param message
         * @param defaultValue
         * @param result
         * @return
         */
        @Override
        public boolean onJsPrompt(WebView view, String url, String message, String defaultValue,
                                  JsPromptResult result) 
            if (resolveJSPrompt(message)) 
                return true;
            
            return super.onJsPrompt(view, url, message, defaultValue, result);
        
    /**
     * JS调用android原生方法3:
     *
     * 通过WebChromeClient的 onJsAlert() onJsConfirm() onJsPrompt() 方法
     * 回调拦截JS对话框alert() confirm() prompt()
     */
    private boolean resolveJSPrompt(String message) 
        Uri uri = Uri.parse(message);
        if (uri.getScheme().equals("js")) 
            if (uri.getAuthority().equals("Authority")) 
                ToastUtil.showToast(APIWebViewActivity.this, "方法3");
            
            return true;
        
        return false;
    

完整源码:

Js调用Native示例源码-JsToNativeBridgeActivity

二、Native调用WebView的两种方案:

1、loadUrl("javascript:callJS()"):

此方法简洁、效率低。当不需要返回值且对性能要求较低时可以考虑使用:

/**
* Native调用JS方法一:
* 方法简洁、效率低
* 当不需要获取返回值且对性能要求较低时可选择使用。
*/
webView.loadUrl("javascript:callJS()");

2、evaluateJavascript(script,resultCallback):

4.4以上才可使用,效率高且有返回值:

/**
 * Native调用JS方法二:
 * 效率高,有返回值(4.4以上系统使用)
 */
webView.evaluateJavascript("javascript:callJS('yao')", new ValueCallback<String>() 
    @Override
    public void onReceiveValue(String value) 
        //此处为JS返回的结果
        Logger.d("value:" + value);
    
);

完整源码:

Native调用JS示例源码-NativeToJsBridgeActivity

以上是关于H5 与Native的交互方案的主要内容,如果未能解决你的问题,请参考以下文章

Hybrid APP之Native和H5页面交互

H5和Native交互原理

H5与Native交互之JSBridge技术

quickhybridH5和Native交互原理

Android中实现Native与H5的通信方案汇总

Android中实现Native与H5的通信方案汇总