Skip to main content

CustomCommand Interface

1 Host CustomCommand Integration​

1.1 Function Introduction​

By using the CustomCommand interface of the Unity host, the host can call the custom interface of the quick application framework, thereby improving some of the host's basic capabilities and platform capabilities.

1.2 Access Instructions​

1.2.1 JS layer calls JAVA layer interface​

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

// Sync
tj.customCommandSync(Object object, String methodName, ...);
Object Parameter Description:​
Parameter NameIs it required?Description
successNoCallback function called when the CustomCommand interface executes successfully. The parameter res contains the execution result, and there can be more than one parameter as required.
failNoCallback function called when the CustomCommand interface fails to execute. The parameter obj contains the following attributes: <li> errorCode, error code </li><li> errorMsg, error message </li>
completeNoCallback function called when the CustomCommand interface execution is completed, with no parameters
Explanation of Other Parameters:​
Parameter NameIs it required?Description
methodNameYesThe name of the Java layer interface that the JS layer needs to call
...Determined by the corresponding methodNameThis parameter is required when executing the corresponding custom interface, and currently supports the following JS types: <li> Basic types: null, boolean, number, string </li><li> typeArray </li><li> Basic arrays: boolean[], number[], string[] (the data types in the array must be consistent) </li>

1.2.2 The Java layer registers this interface through a listener function​

// ASync
void setCustomCommandListener(final CustomCommandListener);
void setCustomCommandListener(String methodName, final CustomCommandListener);

// Sync
Object setSyncCustomCommandListener(final SyncCustomCommandListener);
Object setSyncCustomCommandListener(String methodName, final SyncCustomCommandListener);

1.2.3 JAVA Layer Executes JS Code​

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

1.3 Interface Description:​

Parameter NameIs it required?Description
scriptYesThe string form of the JS code that needs to be executed at the JS layer. Note that Escape Characters should be used to escape special symbols, such as single quotes, double quotes, etc.
listenerNoCallback executed after running script js code, requires overriding the onRunScriptEnd(Bundle args) method

1.4.1 Introduction to the onCallCustomCommand Function​

CustomCommandHandle handle​
Method NameparameterDescription
successNoneCalled after the successful execution of the custom Java interface. After the call, the execution result will be returned to the JS layer, and the corresponding success and complete callbacks will be executed.
failint errorCode,String errorMsgCalled after the execution of a custom Java interface fails. After the call, error information will be returned to the JS layer, and the corresponding fail and complete callbacks will be executed. The errorCode and errorMsg will be passed to the fail callback.
pushResultNon-empty, supported types are shown in the remarks below.The results returned to JS will be cached in the handle in the order of calling pushResult, and after calling handle.success(), the results will be returned as parameters to the success callback of the corresponding tj.customCommand request.

Note: The data types supported by the handle.pushResult() method are: String, boolean, long, double, byte[], short[], int[], float[], double[], boolean[], String[]

If the JS layer requires an object as the success parameter, you can use the JSONObject class to convert it into a json string for passing.

Bundle args​

The Bundle object retrieves corresponding data in the form of key-value pairs. The Unity host will process the parameters passed by JS and package them into a Bundle object. You can refer to the following table to obtain the parameters:

keyData Typevalue
methodNameStringCustomized interface method name
argsNumintNumber of input parameters for the custom interface
typeNCustomCommandArgEnum enumThe Java type of the Nth parameter, based on which the corresponding interface of the bundle can be called to obtain the Nth parameter (counting from 0)
ValueNSupported data types can be seen in the table belowThe value of the Nth parameter. If it is an array, it is necessary to ensure that all elements in the array are of the same JS data type at the JS layer (counting from 0)
Correspondence Table of JS Types and Java Types​
JS TypeJava typeCustomCommandArgEnum enumbundle interface, parameter String key is omitted when writing below
nullnullCC_NULLNone
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()
Example of parsing args: ​
@Override
public void onCallCustomCommand(CustomCommandHandle handle, Bundle args) {
String methodName = args.getString("methodName");
if("XXXXmethodName".equals(methodName)) {
// Validate and extract parameters. Expecting string and number types from JavaScript.
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();
}
}

1.5 Example​

1.5.1 JS layer calls JAVA layer interface​

  1. Create custom.js, and call the tj.customCommand() interface in custom.js
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");
};
  • Set the file directory of the custom script in the startup parameters so that the host will merge the script content under the directory into the execution code when starting up

Custom script directories need to be placed under the assets folder

private TJHostHandle hostHandle;
...
Bundle bundle = new Bundle();
bundle.putString(TjConstants.BUILTIN_CUSTOM_SCRIPTS_PATH, "path to custom scripts directory");
...
hostHandle.setGameStartOptions(bundle);
  • At the Java layer, add the CustomCommandListener monitoring function and process the received data
//Sync methods
// Method 1:
// Use the TjGameHandle object to get the CustomCommand object
CustomCommand customCommand = gameHandle.getCustomCommand();
customCommand.setCustomCommandListener(new CustomCommandListener(){
@Override
public void onCallCustomCommand(CustomCommandHandle handle, Bundle args) {
String methodName = args.getString("methodName");
if("getUserInfo".equals(methodName)) {
// Your own logic here
...
// place the needed information back into the JSONObject
JSONObject userInfo = new JSONObject();
userInfo.put("userId", "");
userInfo.put("userName", "");
handle.pushResult(userInfo.toString);
handle.success();
}
}
})

// Method 2:
customCommand.setCustomCommandListener("getUserInfo", new CustomCommandListener(){
@Override
public void onCallCustomCommand(CustomCommandHandle handle, Bundle args) {
// Your own logic here
...
// place the needed information back into the JSONObject
JSONObject userInfo = new JSONObject();
userInfo.put("userId", "");
userInfo.put("userName", "");
handle.pushResult(userInfo.toString);
handle.success();
}
})

//Async methods
//Method 1:
customCommand.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;
}
});
//Method 2
customCommand.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);
}
}
});

  • The logic within onCallCustomCommand is executed in the game thread, and you can start another sub-thread here to execute business logic

  • The process of parsing the args parameter can be found in Bundle args

1.5.2 Java layer calls JS code​

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);
}
}
});