• JsBridge "Uncaught TypeError: Cannot call method 'callHandler' of undefined", source


    h5和原生结合开发app越来越流行。其实就是webview 的js调用native的方法。也就是需要搭建一个桥。这样的桥早就有人搭建好了,那就是jsbridge。

    git地址:
    https://github.com/lzyzsd/JsBridge.git

    其实很简单,那些添加依赖我就不说了。

    两种情况:
    1.js调用本地的方法:

    webView.loadUrl("http://testopen.cebbank.com/LifePayment/wap/apph5/index.html?uid=111&token=65F34B3203D893AD96173918C80C45B3&telno=16578915632&type=0&canal=yaoyaoshenghuo1&version=1.0.0&macValue=1167DA1CDF6379B94914C8CB5099542C");
    
            webView.registerHandler("wxpay", new BridgeHandler() {
    
    
                @Override
                public void handler(String data, CallBackFunction function) {
    //              Toast.makeText(MainActivity.this, data, Toast.LENGTH_SHORT).show();
                    Gson gson = new GsonBuilder()
    //        2013-09-14 16:45:29
                            .setDateFormat("yyyy-MM-dd HH:mm:ss")
    //                .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
    
                            .create();
    
                    OrderModel ordermodel=gson.fromJson(data,OrderModel.class);
                    requestWXPay(MainActivity.this,ordermodel);
                    Log.i(TAG, "handler: "+ordermodel.getAppid());
                    Log.i(TAG, "handler = submitFromWeb, data from web = " + data);
    //                function.onCallBack("submitFromWeb exe, response data 中文 from Java");
                }
    
            });

    js里面这样写:

        //call native method
                    window.WebViewJavascriptBridge.callHandler(
                        'wxpay'
                        //, {'param': '中文测试'}
                        , data.orderModel
                        , function(responseData) {
                            <!--document.getElementById("show").innerHTML = "send get responseData from java, data = " + responseData-->
                        }
                    );
    1. 本地给js发送消息, 调用网页的方法:
      本地这样写;
    webView.callHandler("payResult", state, new CallBackFunction() {
    
                @Override
                public void onCallBack(String data) {
                    // TODO Auto-generated method stub
    //              Log.i(TAG, "reponse data from js " + data);
                }
    
            });

    js里面这样写:

    function connectWebViewJavascriptBridge(callback) {
            if (window.WebViewJavascriptBridge) {
                callback(WebViewJavascriptBridge)
            } else {
                document.addEventListener(
                    'WebViewJavascriptBridgeReady'
                    , function() {
                        callback(WebViewJavascriptBridge)
                    },
                    false
                );
            }
        }
    
        connectWebViewJavascriptBridge(function(bridge) {
            bridge.init(function(message, responseCallback) {
                console.log('JS got a message', message);
                var data = {
                    'Javascript Responds': '测试中文!'
                };
                console.log('JS responding with', data);
                responseCallback(data);
            });
    
            bridge.registerHandler("payResult", function(data, responseCallback) {
                alert(data);
                document.getElementById("show").innerHTML = ("data from Java: = " + data);
                var responseData = "Javascript Says Right back aka!";
                responseCallback(responseData);
            });
        })

    就是一句户,方法名称对的上就可以了。
    我这里只是总结了一下,其他的基础东西,自己看githup.

    使用jsbridge遇到ssl认证的网站,结果一片空白。也就是https开头的。比如银联支付的页面。那么一开始我就设置了一个处理的webview,

    WebViewClient webviewclient=new WebViewClient(){
                @Override
                public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                    handler.proceed();
                }
            };
    
            webView.setWebViewClient(webviewclient);

    后来,这个webview可以访问银联这种ssl认证的参数,但是不能响应js的调用了。
    一直报错:

    "Uncaught TypeError: Cannot call method 'callHandler' of undefined", source

    我就知道jsbridge肯定自己设置了一个自己的webviewlicent,查看源码库,找到了:

    package coma.github.lzyzsd.jsbridge;
    
    
     private void init() {
            this.setVerticalScrollBarEnabled(false);
            this.setHorizontalScrollBarEnabled(false);
            this.getSettings().setJavaScriptEnabled(true);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                WebView.setWebContentsDebuggingEnabled(true);
            }
            this.setWebViewClient(generateBridgeWebViewClient());
        }
    
        protected BridgeWebViewClient generateBridgeWebViewClient() {
            return new BridgeWebViewClient(this);
        }

    这里,然后这个BridgeWebViewClient我们需要重写,让他支持ssl:

    package coma.github.lzyzsd.jsbridge;
    
    import android.graphics.Bitmap;
    import android.net.http.SslError;
    import android.webkit.SslErrorHandler;
    import android.webkit.WebView;
    import android.webkit.WebViewClient;
    
    import java.io.UnsupportedEncodingException;
    import java.net.URLDecoder;
    
    /**
     * Created by bruce on 10/28/15.
     */
    public class BridgeWebViewClient extends WebViewClient {
        private BridgeWebView webView;
    
        public BridgeWebViewClient(BridgeWebView webView) {
            this.webView = webView;
        }
    
        @Override
        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
    
            handler.proceed();
        }

    ok,既可以使用js,也可以支持ssl。

  • 相关阅读:
    【福利】乳摇动画初探
    碎裂效果尝试(clip-path篇)
    碎裂效果尝试(canvas篇)
    自己的HTML5 播放器
    纯CSS实现选项卡
    企鹅阿里实习生面试
    关于使用indexedDB的本地存储(3)
    关于使用indexedDB的本地存储(2)
    关于使用indexedDB的本地存储(1)
    关于ajax分段上传文件实例~
  • 原文地址:https://www.cnblogs.com/caoxinyu/p/10568751.html
Copyright © 2020-2023  润新知