开放定制化JSAPI
当你创建集成应用是为了提供JSAPI供前端小程序/H5应用使用,你将需要使用以下的扩展能力。
专有钉钉平台提供了以下几个接口组件:
- JsServicePlugin:管理注册扩展jsapi的入口类。
- JsModule:定义扩展jsapi的具体实现类。
- JSRequest:jsapi调用请求对象,可获取请求入参等信息。
- JsResponse:sdk返回执行结果使用。
为了更好的说明如何定义扩展JSAPI,我们假设以下需求场景:
- (假设)我们需要开发一个文档类的定制扩展模块,文档的展示等是通过OA小程序应用展示业务逻辑;OA小程序需要下载、打开并编辑一个文档,而文档的编辑是使用Native代码开发,Native代码就是我们开发的SDK;
- 打开文档的入口在小程序中,因此需要定义openfile的jsapi;
编辑完成后需要将结果返回给小程序,即需要通过startActivityForResult将结果返回给小程序;
定义JsModule
定义打开文档的扩展jsapi:file.open。
示例JsModule的定义:@JSModule
public class JsModuleFile extends JsModule {
@JSMethod("file.open")
public void fileOpen(final JsRequest jsRequest, final JsResponse jsResponse) {
Intent intent = new Intent(jsRequest.context, EditDocActivity.class);
if (jsRequest.params != null) {
intent.putExtra("filePath", jsRequest.params.optString("filePath"));
intent.putExtra("token", jsRequest.params.optString("token"));
}
startActivityForResult(jsRequest, jsResponse, intent, REQUEST_CODE);
// 此处不返回结果,在onActivityResult返回结果
}
@JSMethod("file.delete")
public void fileDelete(final JsRequest jsRequest, final JsResponse jsResponse) {
if (jsRequest.params != null) {
intent.putExtra("filePath", jsRequest.params.optString("filePath"));
//....
}
// 对于常规的扩展jsapi,比如文件删除等,执行完后直接通过JsResponse通知结果
jsResponse.notifySuccess(null);
}
}
关键步骤:
@JSModule注解:标记Jsapi的扩展类
- @JSMethod(“api-name”)注解:定义扩展jsapi,注意被标记的函数的返回值、入参必须固定为以下形态:
public void fun(final JsRequest jsRequest, final JsResponse jsResponse) ;
- JsRequest:可获取前端应用传递过来的参数;
- JsResponse:返回结果
onActivityResult
我们通过startActivityForResult() 打开了EditDocActivity后,需要将EditDocActivity的Result结果返回应前端应用,此时需要使用到onActivityResult函数。
JsModule中提供了两个函数:
‒ startActivityForResult() :用于打开指定Activity;
‒ onActivityResult(): 用于接收Activity的返回result;
请注意,以上两个函数必须配套使用,否则将无法生效。
示例代码:
无论成功还是失败,务必通过JsResponse返回执行结果给前端应用。
@JSModule
public class JsModuleFile extends JsModule {
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent, JsResponse response) {
super.onActivityResult(requestCode, resultCode, intent, response);
if (requestCode == REQUEST_CODE) {
String result = intent.getStringExtra("result");
JSONObject jsonObject = new JSONObject();
jsonObject.put("xxxx", result);
response.notifySuccess(jsonObject);
}
}
}
注意:假如打开的Activity比较耗内存,比如Camera、文档类,如果使用startActivity的方式,可能会造成返回后小程序页面被系统回收清理,因此建议优先使用startActivityForResult()方式打开Activity。
使用JsServicePlugin
定义了JsModule或JsSubject之后,需要将这些对象初始化注入到JsServicePlugin中才能最终生效。
客户端代码示例:
@Extension(id = "dingding_demo_jsbridge", target = JsServicePlugin.EXTENSION_POINT_ID)
public class DemoJSServicePlugin extends JsServicePlugin {
@Override
public void initJsModules() {
JsModuleFile file = new JsModuleFile();
registerJsApi("file.open", file);
registerJsApi("file.delete", file);
}
@Override
public void initJsSubjects() {
}
@Override
public void onDestroy() {
// 清理工作
}
}
- @Extension注解:
- id:当前扩展的id,由开发者自定义,需要保证唯一性,否则会编译失败或导致功能异常,推荐带上特殊标识,例如专有钉钉的开发者可以带上dingding前缀。
- target:当前扩展对应的扩展点id,一般为其父类中的常量,例子中为JsServicePlugin.EXTENSION_POINT_ID
前端调用JSAPI的说明
调用JsModle定义的api
// JSAPI: exclusiveInvoke
// 入参:
// - api:sdk定义的jsapi,比如 "file.open"
// - params:请求的参数
import exclusiveInvoke from 'gdt-jsapi/exclusiveInvoke';
exclusiveInvoke({
api: 'file.open',
params: {
filePath: 'xxxxx',
toekn: 'xxxxx'
}
})