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

Cocos文档-Java原生反射机制

如何在 Android 平台上使用 JavaScript 直接调用 Java 方法 · Cocos Creator

Cocos文档-JSB使用指南

JSB 2.0 使用指南 · Cocos Creatorhttps://docs.cocos.com/creator/manual/zh/advanced-topics/JSB2.0-learning.html

一  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。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android和iOS平台上,可以通过WebView的接口来进行JavaScript和原生代码之间的数据交互。以下是Android和iOS平台上的一些常用方法: ### Android平台 #### 1. WebView.addJavascriptInterface() 该方法可以将Java对象注册到WebView中,使得JavaScript可以通过该对象调用Java中的方法。具体使用方法如下: ```java // 创建一个Java对象 public class MyJavaObject { @JavascriptInterface public void showToast(String message) { Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); } } // 将Java对象注册到WebView中 webView.addJavascriptInterface(new MyJavaObject(), "myJavaObject"); ``` 在JavaScript中,可以通过`window.myJavaObject`来调用MyJavaObject对象中的`showToast()`方法,例如: ```javascript window.myJavaObject.showToast('Hello World!'); ``` #### 2. WebView.evaluateJavascript() 该方法可以在WebView中执行JavaScript代码,并将执行结果传递给指定的回调函数。具体使用方法如下: ```java webView.evaluateJavascript("javascript:alert('Hello World!')", new ValueCallback<String>() { @Override public void onReceiveValue(String value) { // value为JavaScript代码的执行结果 } }); ``` 在上面的例子中,我们通过WebView执行了一段JavaScript代码,即弹出一个提示框,然后将执行结果传递给了回调函数。 ### iOS平台 #### 1. WKWebView.evaluateJavaScript() 该方法可以在WKWebView中执行JavaScript代码,并将执行结果传递给指定的回调函数。具体使用方法如下: ```objective-c [webView evaluateJavaScript:@"alert('Hello World!')" completionHandler:^(id result, NSError *error) { // result为JavaScript代码的执行结果 }]; ``` 在上面的例子中,我们通过WKWebView执行了一段JavaScript代码,即弹出一个提示框,然后将执行结果传递给了回调函数。 #### 2. WKScriptMessageHandler 该协议定义了一个方法,用于处理从JavaScript发送给原生代码的消息。具体使用方法如下: 首先,我们需要创建一个遵循WKScriptMessageHandler协议的对象,并将其注册到WKWebView中: ```objective-c // 创建一个WKUserContentController对象 WKUserContentController *userContentController = [[WKUserContentController alloc] init]; // 创建一个遵循WKScriptMessageHandler协议的对象 MyMessageHandler *messageHandler = [[MyMessageHandler alloc] init]; // 将messageHandler对象注册到userContentController中 [userContentController addScriptMessageHandler:messageHandler name:@"myMessageHandler"]; // 创建一个WKWebViewConfiguration对象,并将userContentController设置为它的userContentController属性 WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init]; configuration.userContentController = userContentController; // 创建一个WKWebView对象,并将configuration设置为它的configuration属性 WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:configuration]; [self.view addSubview:webView]; ``` 然后,在MyMessageHandler对象中实现`userContentController(_:didReceive:)`方法,用于处理从JavaScript发送过来的消息: ```objective-c @interface MyMessageHandler : NSObject <WKScriptMessageHandler> @end @implementation MyMessageHandler - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { // 在这里处理从JavaScript发送过来的消息 NSLog(@"Received message from JavaScript: %@", message.body); } @end ``` 在JavaScript中,可以通过`window.webkit.messageHandlers`对象来发送消息给原生代码,例如: ```javascript window.webkit.messageHandlers.myMessageHandler.postMessage('Hello World!'); ``` 在上面的例子中,我们向名为myMessageHandler的MessageHandler对象发送了一条消息,即字符串'Hello World!'。当原生代码接收到该消息时,会执行MyMessageHandler对象中的`userContentController(_:didReceive:)`方法,并输出接收到的消息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值