# API/组件自定义
如果小程序里需要调用一些宿主 App 提供的能力,而 “人民网+”小程序 SDK 未实现或无法实现时,就可以通过注册自定义 API 来实现,使得小程序里也能够调用 App 中注册的 API 了。
当然,要使用一些未实现或无法实现的组件时,也可以注册自定义组件。
注册自定义 API 分两个场景:
- 注册给原生小程序使用的自定义 API;
- 注册给小程序中 WebView 组件加载的 H5 使用的自定义 API。
# 1. 自定义小程序API
注册自定义小程序api以及使用自定义小程序api有四步:
- 1.实现自定义api
- 2.注册自定义api
- 3.在小程序配置中声明自定义api
- 4.小程序中调用自定义api
# 1.1 注册自定义小程序异步API
1)实现自定义异步api。
# 实现自定义小程序异步api示例
public class CustomApi extends BaseApi {
public CustomApi(Context context) {
super(context);
}
@Override
public String[] apis() {
return new String[]{"customEvent"}; //api名称
}
@Override
public void invoke(String event, JSONObject param, ICallback callback) {
// 调用方法时原生对应的操作
}
}
2)将其注册到extensionApiManager
中,支持单个注册和批量注册。
注册单个自定义api
FinAppClient.extensionApiManager.registerApi(CustomApi(this))
FinAppClient.INSTANCE.getExtensionApiManager().registerApi(new CustomApi(this));
批量注册自定义api
val apis = listOf<IApi>(CustomApi1(), CustomApi2(), CustomApi3())
FinAppClient.extensionApiManager.registerApis(apis)
List<IApi> apis = new ArrayList<>();
IApi customApi1 = new CustomApi1();
apis.add(customApi1);
IApi customApi2 = new CustomApi2();
apis.add(customApi2);
IApi customApi3 = new CustomApi3();
apis.add(customApi3);
FinAppClient.INSTANCE.getExtensionApiManager().registerApis(apis);
3)在小程序配置文件中声明自定义api。
在小程序根目录创建FinClipConf.js
并进行相应的自定义api配置
module.exports = {
extApi:[
{ //普通交互API
name: 'Login', //扩展api名 该api必须Native方实现了
sync: false, //是否为同步api
params: { //扩展api 的参数格式,可以只列必须的属性
url: ''
}
},
{
name: 'TestSync',
sync: true, // 是否为同步api
params: {
name:'',
title:''
}
}
]
}
4)小程序里调用自定义小程序异步api
ft.Login({
url:'https://www.baidu.com',
success: function (res) {
console.log("调用customEvent success");
console.log(res);
},
fail: function (res) {
console.log("调用customEvent fail");
console.log(res);
}
});
# 1.2 注册自定义小程序同步API
同步api是指在调用的时候可以同步返回结果的自定义api。
注意:自定义同步api需要继承SyncApi,并重写同步返回的invoke方法。 同步api必须在小程序进程注册才能生效
1)实现自定义同步api。
public class CustomApi extends SyncApi {
public CustomApi(Context context) {
super(context);
}
@Override
public String[] apis() {
return new String[]{"customApi"};
}
@Nullable
@Override
public String invoke(String event, JSONObject param) {
// {"errMsg": "customApi:ok" , "data": "1"} // 返回的数据格式是固定的,必须是个json格式且包含"errMsg": "customApi:ok" 这一段
return getSuccessRes(event).put("data","1").toString(); // 可以借住sdk提供的api完成对数据的组装
// return getFailureRes(event,"token miss").toString()
}
}
2)在小程序进程注册同步api
class App : Application() {
override fun onCreate() {
super.onCreate()
if (FinAppClient.isFinAppProcess(this)) {
FinAppProcessClient.callback = object : FinAppProcessClient.Callback() {
@Nullable
override fun getRegisterExtensionApis(activity: Activity): List<IApi>? {
// 在小程序进程中注册小程序扩展API
val apis: MutableList<IApi> = ArrayList()
val customApi: IApi = CustomApi(activity)
apis.add(customApi)
return apis
}
@Nullable
override fun getRegisterExtensionWebApis(activity: Activity): List<IApi>? {
// 在小程序进程中注册小程序网页调原生API
val apis: MutableList<IApi> = ArrayList()
val customH5Api: IApi = CustomH5Api(activity)
apis.add(customH5Api)
return apis
}
}
}
}
}
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
if(FinAppClient.INSTANCE.isFinAppProcess(this)){
FinAppProcessClient.INSTANCE.setCallback(new FinAppProcessClient.Callback() {
@Nullable
@Override
public List<IApi> getRegisterExtensionApis(@NotNull Activity activity) {
// 在小程序进程中注册小程序扩展API
List<IApi> apis = new ArrayList<>();
IApi customApi = new CustomApi(activity);
apis.add(customApi);
return apis;
}
@Nullable
@Override
public List<IApi> getRegisterExtensionWebApis(@NotNull Activity activity) {
return new ArrayList<>();
}
});
}
}
}
3)在小程序配置文件中声明自定义api。
在小程序根目录创建FinClipConf.js
并进行相应的自定义api配置
module.exports = {
extApi:[
{ //普通交互API
name: 'Login', //扩展api名 该api必须Native方实现了
sync: false, //是否为同步api
params: { //扩展api 的参数格式,可以只列必须的属性
url: ''
}
},
{
name: 'TestSync',
sync: true, // 是否为同步api
params: {
name:'',
title:''
}
}
]
}
4)小程序里调用
const res = ft.TestSync({'name':'张三', 'title':'“人民网+”'});
console.log(res.title);
# 1.3 取消注册小程序API
支持单个取消注册和批量取消注册。 自定义
取消注册的某个api
# 调用示例
FinAppClient.extensionApiManager.unregisterApi(customApi)
FinAppClient.INSTANCE.getExtensionApiManager().unregisterApi(customApi)
批量取消注册的api
# 调用示例
FinAppClient.extensionApiManager.unregisterApis(apis)
FinAppClient.INSTANCE.getExtensionApiManager().unregisterApis(apis);
# 1.4 获取所有已注册的自定义小程序API
# API
/**
* 获取所有已注册的小程序API
*/
fun getRegisteredApis(): Map<String, IApi>
# 调用示例
val apis = FinAppClient.extensionApiManager.getRegisteredApis()
Map<String, IApi> apis = FinAppClient.INSTANCE.getExtensionApiManager().getRegisteredApis();
# 2. 自定义 WebView 组件API
小程序里加载的H5,如果也想调用宿主API的某个能力,就可以利用该方法注册一个API。 目前仅支持注册异步api。
注册自定义webView Api和使用webView Api有三步:
- 1.实现自定义api
- 2.注册自定义api。
- 3.H5中调用自定义api。
# 2.1 注册WebView 组件API
- 实现自定义api。
# 自定义api示例
public class WebApi extends BaseApi {
public WebApi(Context context) {
super(context);
}
@Override
public String[] apis() {
return new String[]{"webApiName"}; //api名称
}
@Override
public void invoke(String event, JSONObject param, ICallback callback) {
// 调用方法时原生对应的操作
}
}
- 将其注册到
extensionWebApiManager
中,支持单个注册和批量注册。
注册单个自定义api
FinAppClient.extensionWebApiManager.registerApi(WebApi(this))
FinAppClient.INSTANCE.getExtensionWebApiManager().registerApi(new WebApi(this));
批量注册自定义api
val apis = listOf<IApi>(WebApi1(), WebApi2(), WebApi3())
FinAppClient.extensionWebApiManager.registerApis(apis)
List<IApi> apis = new ArrayList<>();
IApi webApi1 = new WebApi1();
apis.add(webApi1);
IApi webApi2 = new WebApi2();
apis.add(webApi2);
IApi webApi3 = new WebApi3();
apis.add(webApi3);
FinAppClient.INSTANCE.getExtensionWebApiManager().registerApis(apis);
3)在H5内调用自定义api
在H5内引用我们的桥接JSSDK文件,即可调用上面的注册的方法了。
HTML内调用注册的方法示例:
window.ft.miniProgram.callNativeAPI('js2AppFunction', {name:'getLocation'}, (result) => {
console.log(result)
});
# 2.2 取消注册 WebView 组件API
支持单个取消注册和批量取消注册。
取消单个WebView 组件API
# 调用示例
FinAppClient.extensionWebApiManager.unregisterApi(webApi)
FinAppClient.INSTANCE.getExtensionWebApiManager().unregisterApi(webApi)
批量取消WebView 组件API
FinAppClient.extensionWebApiManager.unregisterApis(webApis)
FinAppClient.INSTANCE.getExtensionWebApiManager().unregisterApis(webApis);
# 2.3 获取所有已注册的小程序 WebView API
# API
/**
* 获取所有已注册的网页调用的原生API
*/
fun getRegisteredApis(): Map<String, IApi>
# 调用示例
val apis = FinAppClient.extensionWebApiManager.getRegisteredApis()
Map<String, IApi> apis = FinAppClient.INSTANCE.getExtensionWebApiManager().getRegisteredApis();
# 3. 在小程序进程中注册api
正常情况下注册到小程序的api是在主进程调用执行的,当有需要在小程序进程执行的api的时候,需要调用另外的接口去注册。
FinAppProcessClient.callback = object : FinAppProcessClient.Callback {
override fun getRegisterExtensionApis(activity: Activity): List<IApi>? {
// 在小程序进程中注册小程序扩展API
return listOf(CustomApi(activity))
}
override fun getRegisterExtensionWebApis(activity: Activity): List<IApi>? {
// 在小程序进程中注册小程序网页调原生API
return listOf(CustomH5Api(activity))
}
}
FinAppProcessClient.INSTANCE.setCallback(new FinAppProcessClient.Callback() {
@Nullable
@Override
public List<IApi> getRegisterExtensionApis(@NotNull Activity activity) {
// 在小程序进程中注册小程序扩展API
List<IApi> apis = new ArrayList<>();
IApi customApi = new CustomApi(activity);
apis.add(customApi);
return apis;
}
@Nullable
@Override
public List<IApi> getRegisterExtensionWebApis(@NotNull Activity activity) {
// 在小程序进程中注册小程序网页调原生API
List<IApi> apis = new ArrayList<>();
IApi customH5Api = new CustomH5Api(activity);
apis.add(customH5Api);
return apis;
}
});
# 4. 原生调用 JS API
# API
/**
* 原生调用JS函数
*
* @param appId 小程序id
* @param funcName JS函数名
* @param funcParams JS函数参数
* @param webViewId WebView的id
* @param callback 回调
*/
fun callJS(appId: String, funcName: String?, funcParams: String?, webViewId: Int, callback: FinCallback<String?>)
# 调用示例
FinAppClient.appletApiManager.callJS(
"appId",
"funcName",
"funParams",
1,
object : FinCallback<String?> {
override fun onSuccess(result: String?) {
Log.d(TAG, "callJS onSuccess : $result")
}
override fun onError(code: Int, error: String?) {
Log.d(TAG, "callJS onError : $code:, $error")
}
override fun onProgress(status: Int, info: String?) {
}
})
FinAppClient.INSTANCE.getAppletApiManager().callJS(
"appId",
"funcName",
"funParams",
1,
new FinCallback<String>() {
@Override
public void onSuccess(String result) {
Log.d(TAG, "callJS onSuccess : " + result);
}
@Override
public void onError(int code, String error) {
Log.d(TAG, "callJS onError : " + code + ", " + error);
}
@Override
public void onProgress(int status, String info) {
}
});
首先,在H5内引用我们的桥接JSSDK文件。
然后,在HTML里注册好方法,比如方法名叫app2jsFunction
。
window.ft.miniProgram.registNativeAPIHandler('app2jsFunction', function(res) {
// app2jsFunction callback
})
# 5. 注册原生组件
由于资源有限,livePusher 和livePlayer等原生组件的实现可能需要借助外部的第三方控件,这时候就可以注册原生组件。我们现在支持注册的原生组件有三个:Camera、LivePlayer、LivePusher。
# 5.1 实现自定义的原生组件
实现INativeView接口
# 示例
class TestNativeView : INativeView {
lateinit var eventChannel: INativeView.EventChannel
/**
* 创建nativeview
* @param params 小程序中传来的参数
* @param eventChannel 用来向小程序组件发送事件
* @return 创建的view,会填充到小程序里声明组件的位置
*/
override fun onCreateView(
context: Context,
params: ShowNativeViewParams,
eventChannel: INativeView.EventChannel
): View {
Log.d(TAG, "onCreateView:${params.nativeViewId}")
this.eventChannel = eventChannel
return TextView(context).apply {
gravity = Gravity.CENTER
setTextColor(Color.RED)
text = params.params.toString()
setBackgroundColor(Color.GREEN)
setOnClickListener {
eventChannel.send(
"test",
mapOf("time" to System.currentTimeMillis())
)
}
}
}
/**
* 更新nativeview
* @param params 小程序中传来的参数
* @param view 之前创建的view
*/
override fun onUpdateView(context: Context, params: ShowNativeViewParams, view: View) {
Log.d(TAG, "onUpdateView:${params.nativeViewId}")
params.params?.let { (view as TextView).text = it.toString() }
}
/**
* 销毁nativeview
* @param params 小程序中传来的参数
* @param view 之前创建的view
*/
override fun onDestroyView(context: Context, nativeViewId: String, view: View) {
Log.d(TAG, "onDestroyView:$nativeViewId")
}
}
# 5.2 注册原生组件
# API
/**
* 注册原生组件
*
* @param type 组件类型
* @param cls 组件实现类 需实现INativeView接口
*/
fun registerNativeView(type: String, cls: Class<out INativeView>)
# 调用示例
# ·Kotlin
FinAppClient.nativeViewManager.registerNativeView("video", TestNativeView::class.java)