Cocos creator H5与Java的交互

最近公司要求做一款h5游戏嵌入app,我用的游戏引擎是Cocos creator TS发布h5。所以首先要解决的就是交互问题,方便互相之间获取数据。我改写了网上的jsbridge demo用以适应自己的工程,也做了进一步解释。

参考的原工程:https://github.com/lzyzsd/JsBridge 

 

  • 安卓部分

在Android Studio上创建library实现jsbridge模块放入app中。

创建BridgeWebView类继承安卓的WebView在类中实现基本的初始化设置

      getSettings().setJavaScriptEnabled(true);
      getSettings().setDomStorageEnabled(true);
      getSettings().getJavaScriptCanOpenWindowsAutomatically();
      getSettings().setAllowUniversalAccessFromFileURLs(true);

在该类中实现调用js的方法 callJavaScriptFunc(String funcName, Object params, IBridgeCallback responseCall)

js在注册表中通过funcName找到对应方法执行,如果需要js返回结果数据,则添加responseCall,java派发这一方法

时在responseCall中添加对应的id以方便js执行完对应的方法后携带该id返回数据,java通过该id接收执行responseCall

中对应的回调拿到返回数据

/**
  * 调用JavaScript的方法
  * @param funcName JavaScript方法名
  * @param params 参数 JSON/String
  * @param responseCall
  */
public void callJavaScriptFunc(String funcName, Object params, IBridgeCallback responseCall){
        // 没有方法名 return
        if(TextUtils.isEmpty(funcName)) return;
        // 参数不是String Gosn无实例对象 return
        if(!(params instanceof String) && _jsonUtil == null) return;

        JSRequest request = new JSRequest();
        request._funcName = funcName;
        request._funcParam = (params instanceof String)?(String)params:_jsonUtil.toJson(params);

        if(responseCall != null){
            String key = BridgeConfig.BRIDGE_CALL_KEY + (++_callbackId);
            request._callFuncKey = key;
            _responseCallMap.put(key, responseCall);
        }

        dispatchMessageToJS(request, BridgeDispatchType.DispatchCallFunc);
    }

原工程中派发方法和派发返回数据都是走的同一方法,我将其分开了。返回结果给js也是通过查看js调用java方法时是否携带

回调函数的id如果有就代表需要返回数据,返回数据时将js传过来的id一并返回,js通过该id执行对应的回调拿到Java给的返回

数据。

    /**
     * 返回数据给JavaScript
     * @param responseData 返回的数据
     * @param callFuncKey JavaScript注册的回调函数的key
     */
    public void responseToJavascript(Object responseData, String callFuncKey) {
        if (TextUtils.isEmpty(callFuncKey)) return;

        if (!(responseData instanceof String) && _jsonUtil == null) return;

        final JSResponse response = new JSResponse();
        response._callFuncKey = callFuncKey;
        response._responseData = responseData instanceof String ? (String) responseData : _jsonUtil.toJson(responseData);
        if (Thread.currentThread() == Looper.getMainLooper().getThread()){
            dispatchMessageToJS(response, BridgeDispatchType.DispatchResponse);
        }else {
            post(new Runnable() {
                @Override
                public void run() {
                    dispatchMessageToJS(response, BridgeDispatchType.DispatchResponse);
                }
            });
        }
    }

在给js传输数据时需要在主线程中传输,在H5页面加载完成后注入jsWebBridge.js对象 

    @Override
    public void onPageFinished(WebView view, String url) {
        if (_webViewClient != null) {
            _webViewClient.onPageFinished(view, url);
        } else {
            super.onPageFinished(view, url);
        }
        // 注入jsWebBridge.js对象
        BridgeUtil.LoadLocalJS(view, BridgeConfig.JS_BRIDGE_SCRIPT);
    }
  •  jsWebBridge.js对象

java调用js方法需要在js端先注册对应的方法,因为jsWebBridge.js是在h5加载之后才注入,如果在此对象还不存在时注册

js方法不会成功,所以需要做回调执行,通过监听该对象生成后再执行注册

    var doc = document;
    var readyEvent = doc.createEvent('Events');
    readyEvent.initEvent('jsWebBridgeReady');
    readyEvent.bridge = jsWebBridge;
    doc.dispatchEvent(readyEvent);

在注册前可以先监听jsWebBridgeReady事件,再执行以下方法 

 

    // register js func for java call
    function registerFuncForJava(funcName, func){
        registerFuncMap[funcName] = func;
    }

js调用java方法时和java调用js一样的原理,如果需要返回数据则将回调函数添加一个id存储起来,java返回时查找id调用

这里调用java方法是通过java指定的android对象去调用

    // js call java func
    function callJavaFunc(funcName, params, callback){
        var callbackId;
        if (callback){
            callbackId = BRIDGE_CALL_KEY + (++_callbackId);
            responseCallMap[callbackId] = callback;
        }
        if (funcName){
            try{
                eval("window.android." + funcName + "('"+JSON.stringify(params)+"','"+callbackId+"')");
            }catch(exception){
                if (typeof console != 'undefined'){
                    console.log('jsWebBridge: callJavaFunc java func call fail >>' + funcName);
                }
            }
        }
    }

java调用js方法,js在注册表中查找对应的方法执行,并且调用java的方法返回数据 

   // java call js func
    function callFuncFromJava(message){
    	var msgJson = JSON.parse(message);
        var responseCall = null;
        var jsFunc = null;
        if (msgJson._funcName) {
            jsFunc = registerFuncMap[msgJson._funcName];
        }
        if (msgJson._callFuncKey){
            console.log("there is a callback id = " + msgJson._callFuncKey);
            responseCall = function(responseData){
                sendResponseToJava(msgJson._callFuncKey, responseData);
            }
        }
        if (jsFunc){
            try{
                jsFunc(msgJson._funcParam, responseCall);
            }catch(exception){
                if (typeof console != 'undefined'){
                    console.log('jsWebBridge: callFuncFromJava javascript func call fail >>' + msgJson._funcName);
                }
            }
        }
    }
  •  Cocos creator部分

创建一个类用来实现js的方法注册以及java的方法调用,不做过多解释,代码有注释

/**
     * 注册可以供native调用的方法
     * (if:如果jsWebBridge对象已存在直接注册)
     * (else:如果jsWebBridge对象不存在等待jsWebBridgeReady.js加载完给通知再执行注册)
     * @param funcName 注册的方法名称
     * @param func 注册的方法(example: function(params, responseCall) params:java传的参数 responseCall:回传数据时调用)
     *  在回调中如果有对creator ui操作要用event事件派发,否则会操作失败
     */
    registerFunc(funcName: string, func: Function){
        if(window['jsWebBridge']){
            window['jsWebBridge'].registerFuncForJava(funcName, func);
        }else{
            document.addEventListener(
                "jsWebBridgeReady",
                 function() {
                    window['jsWebBridge'].registerFuncForJava(funcName, func);
                 },
                 false);
        }
    }

    /* 
        example:

        registerFunc("testCallFromJava", testCallFromJava)

        testCallFromJava(params, responseCall:Function){
            EventManager.getInstance().emit("register", params, responseCall)
        }
    */


    /**
     * 调用Java方法
     * @param funcName 方法名
     * @param params 参数
     * @param receiveCall 接收Java返回的数据函数(在回调中如果有对creator ui操作的行为要用event事件派发)
     */
    callJavaFunc(funcName:string, params, receiveCall:Function){
        if (window['jsWebBridge']){
            window['jsWebBridge'].callJavaFunc(funcName, params, receiveCall)
        }
    }

Demo地址:https://pan.baidu.com/s/1vnJyxih_aqb7Ymvv2MwpYQ

提取码:2ojd

 

 

 

 

 

 

 

你可能感兴趣的:(日记)