跳到主要内容

CustomCommand 接口

1. 宿主 CustomCommand 接入​

功能介绍​

通过使用团结宿主的 CustomCommand 接口,可以使得宿主调取到快应用框架的自定义接口,使宿主的部分基础能力和平台能力得到完善。

接入说明​

JS 层调用 JAVA 层接口​

// 异步
tj.customCommand(Object object, string methodName, ...);

// 同步
tj.customCommandSync(Object object, String methodName, ...);
Object 参数说明:​
参数名是否必填描述
success否CustomCommand 接口执行成功时调用的回调函数,参数 res 中包含执行结果,按需求可以有不止一个参数。
fail否CustomCommand 接口执行失败时调用的回调函数,参数 obj 包含以下属性:
  • errorCode,错误代码
  • errorMsg,错误信息
  • complete否CustomCommand 接口执行完成时调用的回调函数,无参数
    其他参数说明:​
    参数名是否必填描述
    methodName是JS 层需要调到的 Java 层的接口名称
    ...由对应的 methodName 决定此参数为执行对应自定义接口时需要传递的参数,目前支持以下 JS 类型:
  • 基本类型:null,boolean,number,string
  • typeArray
  • 基本数组:boolean[],number[],string[] (数组中数据类型需保持一致)
  • Java 层通过监听函数注册此接口​

    // 同步
    void setCustomCommandListener(final CustomCommandListener);
    void setCustomCommandListener(String methodName, final CustomCommandListener);

    // 异步
    Object setSyncCustomCommandListener(final SyncCustomCommandListener);
    Object setSyncCustomCommandListener(String methodName, final SyncCustomCommandListener);

    JAVA 层执行 JS 代码​

    hostHandle.runCustomscript(final String script, final RunScriptListener listener);

    接口说明:​

    参数名是否必填描述
    script是需要 JS 层执行的 JS 代码的字符串形式。注意使用转义字符将特殊符号进行转义,例如单引号、双引号等。
    listener否执行 script js 代码后执行的回调,需要重写 onRunScriptEnd(Bundle args) 方法

    相关 API​

    onCallCustomCommand 函数介绍​

    CustomCommandHandle handle​
    方法名参数描述
    success无执行自定义 java 接口成功后调用,调用后会将执行结果返回给 JS 层,并执行相应 success、complete 回调。
    failint errorCode,String errorMsg执行自定义 java 接口失败后调用,调用后会将错误信息返回给 JS 层,并执行相应 fail、complete 回调。errorCode 与 errorMsg 会传给 fail 回调。
    pushResult非空,支持的类型见下方备注。返回给 JS 的结果会按照调用 pushResult 的顺序依次先缓存到 handle 中,等调用 handle.success() 后会把结果以参数的形式返回给对应 tj.customCommand 请求的 success 回调。
    备注:handle.pushResult() 方法支持的数据类型有: String、boolean、long、double、byte[]、short[]、int[]、float[]、double[]、boolean[]、String[]​
    若 JS 层需要 object 对象作为 success 入参,可使用 JSONObject 类转换成 json 字符串传递。​
    Bundle args​

    Bundle 对象通过 key-value 的形式获取对应数据,团结宿主会处理 JS 传递的参数并包装成 Bundle 对象,可参照下表获取参数:

    key数据类型value
    methodNameString自定义的接口方法名
    argsNumint自定义接口的入参数量
    typeNCustomCommandArgEnum enum第 N 个参数的 Java 类型,可根据此类型调用 bundle 对应的接口来获取第 N 个参数(从0开始计数)
    ValueN支持的数据类型可见下方表格第 N 个参数的值。如果是数组,需在 JS 层保证数组中均为同一种 JS 数据类型(从0开始计数)
    js 类型与 java 类型对应表​
    js 类型java 类型CustomCommandArgEnum enumbundle 接口,下方书写时省略参数 String key
    nullnullCC_NULL无
    booleanbooleanCC_BOOLEANgetBoolean()
    numbernumberCC_NUMBERgetDouble()
    stringStringCC_STRINGgetString()
    Int8Arraybyte[]CC_BYTE_ARRAYgetByteArray()
    Int16Arrayshort[]CC_SHORT_ARRAYgetShortArray()
    Int32Arrayint[]CC_INT_ARRAYgetIntArray()
    Float32Arrayfloat[]CC_FLOAT_ARRAYgetFloatArray()
    Float64Arraydouble[]CC_DOUBLE_ARRAYgetDoubleArray()
    [boolean]boolean[]CC_BOOLEAN_ARRAYgetBooleanArray()
    [number]number[]CC_NUMBER_ARRAYgetDoubleArray()
    [string]String[]CC_STRING_ARRAYgetStringArray()
    解析 args 示例:​
    @Override
    public void onCallCustomCommand(CustomCommandHandle handle, Bundle args) {
    String methodName = args.getString("methodName");
    if("XXXXmethodName".equals(methodName)) {
    // 检查、获取参数,假设已知 js 那边需要传 string、double 参数
    int argsNum = args.getInt("argsNum");
    if((CustomCommandArgEnum)args.getSerializable("type0") != CustomCommandArgEnum.CC_STRING) {
    handle.fail(13000001, "params error, require String");
    return;
    }
    if((CustomCommandArgEnum)args.getSerializable("type1") != CustomCommandArgEnum.CC_NUMBER) {
    handle.fail(13000001, "params error, require Double");
    return;
    }
    String param1 = args.getString("value0");
    double param2 = args.getDouble("value1");
    // ....
    handle.success();
    }
    }

    示例​

    JS 层调用 JAVA 层接口​

    1. 创建 custom.js,在 custom.js 中调用 tj.customCommand() 接口
    tj.getUserInfo = function (callback) {
    tj.customCommand(
    {
    success: function (res) {
    try {
    let userInfo = JSON.parse(res);
    callback(userInfo);
    } catch (e) {
    let errorMsg = "parse userInfo failed";
    callback(errorMsg);
    }
    },
    fail: function (obj) {
    // 获取用户信息失败
    console.info("getUserInfo failed : " + obj.errorMsg);
    },
    complete: function () {
    // 获取用户信息完成
    console.info("getUserInfo completed");
    },
    },
    "getUserInfo",
    );
    };

    tj.getUserInfoSync = function () {
    return tj.customCommandSync("getUserInfoSync");
    };
    1. 在启动参数中设置自定义脚本的文件目录,这样宿主在启动时会将目录下的脚本内容合并进执行代码中

    自定义脚本目录需要放在 assets 文件夹下

    private TJHostHandle hostHandle;
    ...
    Bundle bundle = new Bundle();
    bundle.putString(TjConstants.BUILTIN_CUSTOM_SCRIPTS_PATH, "path to custom scripts directory");
    ...
    hostHandle.setGameStartOptions(bundle);
    1. 在 java 层,添加 CustomCommandListener 监听函数,并处理收到的数据
    // 同步
    // 方式一:
    // 通过 TJHostHandle 对象设置监听函数
    hostHandle.setCustomCommandListener(new CustomCommandListener(){
    @Override
    public void onCallCustomCommand(CustomCommandHandle handle, Bundle args) {
    String methodName = args.getString("methodName");
    if("getUserInfo".equals(methodName)) {
    // 根据具体逻辑获得用户信息
    ...
    // 将需要返回的信息放入 JSONObject 中
    JSONObject userInfo = new JSONObject();
    userInfo.put("userId", "");
    userInfo.put("userName", "");
    handle.pushResult(userInfo.toString);
    handle.success();
    }
    }
    })

    // 方式二:
    hostHandle.setCustomCommandListener("getUserInfo", new CustomCommandListener(){
    @Override
    public void onCallCustomCommand(CustomCommandHandle handle, Bundle args) {
    // 根据具体逻辑获得用户信息
    ...
    // 如果需要返回 object 的话,需要将 object 的信息放入 JSONObject 中
    JSONObject userInfo = new JSONObject();
    userInfo.put("userId", "");
    userInfo.put("userName", "");
    handle.pushResult(userInfo.toString);
    handle.success();
    }
    })

    // 异步
    //方式一
    hostHandle.setSyncCustomCommandLister(new SyncCustomCommandListener() {
    @Override
    public Object onCallSyncCustomCommandListener(Bundle args) {
    String methodName = args.getString("methodName");
    if(methodName.equals("getUserInfoSync")) {
    JSONObject jsonObject = new JSONObject();
    try {
    jsonObject.put("EnglishName", "kevin");
    jsonObject.put("NickName", "xiaoxin");
    String result = jsonObject.toString();
    return result;
    } catch (JSONException e) {
    throw new RuntimeException(e);
    }
    }
    return null;
    }
    });
    //方式二
    hostHandle.setSyncCustomCommandLister("getUserInfoSync", new SyncCustomCommandListener() {
    @Override
    public Object onCallSyncCustomCommandListener(Bundle args) {
    JSONObject jsonObject = new JSONObject();
    try {
    jsonObject.put("EnglishName", "kevin");
    jsonObject.put("NickName", "xiaoxin");
    String result = jsonObject.toString();
    return result;
    } catch (JSONException e) {
    throw new RuntimeException(e);
    }
    }
    });
    • onCallCustomCommand 内的逻辑在游戏线程中执行,可以在此另起子线程来执行业务逻辑
    • 解析 args 参数的过程可见 Bundle args

    Java 层调用 JS 代码​

    String script = "var res1 = tj.getUserInfoSync(); return res1;";
    hostHandle.runCustomScript(script, new RunScriptListener() {
    @Override
    public void onRunScriptEnd(Bundle args) {
    if((CustomCommandArgEnum)args.getSerializable("type") != CustomCommandArgEnum.CC_STRING) {
    Log.d(TAG, "params error");
    return ;
    }
    try {
    JSONObject jsonObject = new JSONObject(args.getString("value"));
    String englishName = jsonObject.getString("EnglishName");
    Log.d(TAG, "English Name is " + englishName);
    } catch (JSONException e) {
    throw new RuntimeException(e);
    }
    }
    });