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 Name | Is it required? | Description |
|---|---|---|
| success | No | Callback 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. |
| fail | No | Callback 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> |
| complete | No | Callback function called when the CustomCommand interface execution is completed, with no parameters |
Explanation of Other Parameters:
| Parameter Name | Is it required? | Description |
|---|---|---|
| methodName | Yes | The name of the Java layer interface that the JS layer needs to call |
| ... | Determined by the corresponding methodName | This 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 Name | Is it required? | Description |
|---|---|---|
| script | Yes | The 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. |
| listener | No | Callback executed after running script js code, requires overriding the onRunScriptEnd(Bundle args) method |
1.4 Related APIs
1.4.1 Introduction to the onCallCustomCommand Function
CustomCommandHandle handle
| Method Name | parameter | Description |
|---|---|---|
| success | None | Called 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. |
| fail | int errorCode,String errorMsg | Called 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. |
| pushResult | Non-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:
| key | Data Type | value |
|---|---|---|
| methodName | String | Customized interface method name |
| argsNum | int | Number of input parameters for the custom interface |
| typeN | CustomCommandArgEnum enum | The 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) |
| ValueN | Supported data types can be seen in the table below | The 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 Type | Java type | CustomCommandArgEnum enum | bundle interface, parameter String key is omitted when writing below |
|---|---|---|---|
| null | null | CC_NULL | None |
| boolean | boolean | CC_BOOLEAN | getBoolean() |
| number | number | CC_NUMBER | getDouble() |
| string | String | CC_STRING | getString() |
| Int8Array | byte[] | CC_BYTE_ARRAY | getByteArray() |
| Int16Array | short[] | CC_SHORT_ARRAY | getShortArray() |
| Int32Array | int[] | CC_INT_ARRAY | getIntArray() |
| Float32Array | float[] | CC_FLOAT_ARRAY | getFloatArray() |
| Float64Array | double[] | CC_DOUBLE_ARRAY | getDoubleArray() |
| [boolean] | boolean[] | CC_BOOLEAN_ARRAY | getBooleanArray() |
| [number] | number[] | CC_NUMBER_ARRAY | getDoubleArray() |
| [string] | String[] | CC_STRING_ARRAY | getStringArray() |
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
- 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);
}
}
});