• 【原生】CocosCreator Android和游戏的通讯 (Java和TS互相调用、传递JSON数据、监听返回键)


    Cocos版本:2.4.4

    参考:

    Cocos文档-Java原生反射机制

    Cocos文档-JSB使用指南

    一  Cocos中调用Android方法

    二 Android中调用Cocos方法

    三 传递JSON数据

    四 监听返回键 

    五 遇到的问题

    cocos和android的互相调用,在Java中可以调用TypeScript的方法,在TypeScript中可以调用Java的方法。

    一 Cocos中调用Android方法: jsb.reflection.callStaticMethod

    通过反射机制直接在 JavaScript 中调用 Java 的静态方法。

    反射机制:Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。

    在android的AppActivity中定义一个方法

    在cocos中调用Android定义的方法,传递参数hello。

        start(){
            let result = jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "AndroidFun", "(Ljava/lang/String;)Ljava/lang/String;", "hello");
        }
    

      

    运行android项目,可以看到调用成功

     

    二 Android中调用Cocos的方法:Cocos2dxJavascriptJavaBridge.evalString

     在Cocos的MainScene.ts中定义方法

    MainScene.ts需要赋值给cc,不然android访问不到这个方法,这段代码必须放在android调用cocos方法之前,可以游戏初始化时执行这段代码。

    目前引擎并未承诺多线程下的安全性,所以在开发过程中需要避免 JS 代码在其他线程被调用,以避免各种内存错误,一定要在 GL 线程中执行。

     android调用cocos方法。

            org.cocos2dx.lib.Cocos2dxHelper.runOnGLThread(new Runnable() {
                @Override
                public void run() {
                    org.cocos2dx.lib.Cocos2dxJavascriptJavaBridge.evalString("cc["MainScene"].CocosFun("abc")");
                }
            });
    

      

    运行项目,可以看到android已经成功调用了cocos的方法,并输出了调试信息

     三 传递JSON数据

     原生和cocos的互相传递json消息,因为json可以自定义各种数据,比较方便。

    Cocos中派发和接收Android的消息

    MainScene.ts:

        /**
         * 发送消息到安卓
         * @param data object(json格式)
         */
        public static postMessageToAndroid(data) {
            let str = JSON.stringify(data);
            console.log("[MainScene] postMessageToAndroid:", str);
            let result = jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "revJsMessage", "(Ljava/lang/String;)Ljava/lang/String;", str);
        }
    
        /**
         * 接收来自安卓的原生消息
         * @param data json格式字符串
         */
        public static revAndroidMsg(data) {
            let json = JSON.parse(data);
            let cmd = json.cmd;
            switch (cmd) {
                case 1001:
                    console.log("[MainScene] revAndroidMsg:", cmd, json.msg);
                    break;
            }
        }
    

      

    Android中派发和接收Cocos消息

    android中的json使用JsonObject,jsonObject.toString()将json转成字符串后通过evalString接口传递。

    传递的json数据需要用replace(""", "\"")特殊处理,将原本{"cmd":1001,"msg":"I'm Android"} 字符串转成  {"cmd":1001,"msg":"I'm Android"},通过转义字符来处理引号""嵌套导致的问题。

    AppActivity.java:

        /**
         * 发送消息给JS
         * @param data JSONObject格式消息
         */
        public static void postMessageToJs(final JSONObject data){
            org.cocos2dx.lib.Cocos2dxHelper.runOnGLThread(new Runnable() {
                @Override
                public void run() {
                    String str = data.toString();
                    str = str.replace(""", "\"");
                    Log.v("v","[Android] postMessageToJs:" + str);
                    org.cocos2dx.lib.Cocos2dxJavascriptJavaBridge.evalString("cc["MainScene"].revAndroidMsg("" + str + "")");
                }
            });
        }
    
        /**
         * 接收来自JS的消息
         * @param data json格式字符串
         * @return 返回数据
         */
        public static String revJsMessage(String data) {
            Log.v("v","[Android] revJsMessage:" + data);
            try{
                JSONObject revObj = new JSONObject(data);
                int cmd = revObj.getInt("cmd");
                switch (cmd){
                    case 1001:
                        //打印收到的JS消息
                        String msg = revObj.getString("msg");
                        Log.v("v","[Android] revJsMessage:" + msg);
                        //给JS发送一个消息
                        JSONObject object = new JSONObject();
                        object.put("cmd",1001);
                        object.put("msg","I'm Anroid");
                        AppActivity.postMessageToJs(object);
                        break;
                }
            }catch (JSONException e){
                e.printStackTrace();
            }
            return "";
        }
    

    测试例子

    从cocos中传递命令号1001,数据I'm JS给Android,Android收到后返回一个I'm Android给Cocos。

     start(){      
           //派发事件给android
            cc["MainScene"] = MainScene;
            let obj:any = {};
            obj.cmd = 1001;
            obj.msg = "I'm JS";
            MainScene.postMessageToAndroid(obj);
    }
    

    android studio输出信息   

    四 监听返回键

    android中使用onKeyDown监听返回键,当用户点击返回键或使用手势返回时,派发事件2001给Cocos。

    AppActivity.java:

        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            //点击返回键  getRepeatCount()是重复次数,为防止点击过快或长按导致不停派发事件
            if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
                try{
                    JSONObject object = new JSONObject();
                    object.put("cmd",2001);
                    AppActivity.postMessageToJs(object);
                }catch (JSONException e){
    
                }
                return false;
            }
            return false;  //false 继续传播事件  true停止传播事件
        }
    

      

    cocos监听到返回键事件2001,弹出一个确认框,用户点击取消则关闭弹框;用户点击确认则发送事件2002给android,告知android可以退出游戏。

     MainScene.ts:

        /**
         * 接收来自安卓的原生消息
         * @param data json格式字符串
         */
        public static revAndroidMsg(data) {
            let json = JSON.parse(data);
            let cmd = json.cmd;
            console.log("[MainScene] revAndroidMsg:",json.cmd);
            switch (cmd) {
                case 1001:
                    
                    break;
                case 2001:  //点击返回键
                    App.Panel.open(AssetConst.ConfirmPanel,  {
                        msg: "是否退出游戏?",
                        okCB: ()=>{           //确认回调
                            let data = {cmd:2002};
                            MainScene.postMessageToAndroid(data)
                        },         
                        target: this,       //回调执行对象
                        okStr: "退出",      //确认按钮文本
                    });
                    break;
            }
        }
    

    android收到2002事件,调用System.exit(0)关闭app应用。  

    AppActivity.java:

        /**
         * 接收来自JS的消息
         * @param data json格式字符串
         * @return 返回数据
         */
        public static String revJsMessage(String data) {
            Log.v("v","[Android] revJsMessage:" + data);
            try{
                JSONObject revObj = new JSONObject(data);
                int cmd = revObj.getInt("cmd");
                switch (cmd){
                    case 1001:
    
                        break;
                    case 2002:  //退出
                        System.exit(0);
                        break;
                }
            }catch (JSONException e){
                e.printStackTrace();
            }
            return "";
        }
    

      

     

    五 遇到问题

    1 没有自动import

    安卓没有自动import,提示找不到Cocos2dxJavascriptJavaBridge,也找不到app,所以我写的全路径,也可以自己手动import。

     

      

  • 相关阅读:
    nyoj----522 Interval (简单树状数组)
    HDUOJ-----2838Cow Sorting(组合树状数组)
    HDUOJ---2642Stars(二维树状数组)
    HDUOJ -----Color the ball
    ACM遇到的问题与解决方案
    ELK架构下利用Kafka Group实现Logstash的高可用
    Linux给力的Shell命令
    i18n 语言码和对应的语言库
    jar启动脚本shell
    持续集成和部署工具GOCD
  • 原文地址:https://www.cnblogs.com/gamedaybyday/p/15048113.html
Copyright © 2020-2023  润新知