# API/组件自定义
如果小程序里需要调用一些宿主 App 提供的能力,而 FinClip 小程序 SDK 未实现或无法实现时,就可以通过注册自定义 API 来实现,使得小程序里也能够调用 App 中注册的 API 了。
当然,要使用一些未实现或无法实现的组件时,也可以注册自定义组件。
注册自定义 API 分两个场景:
- 注册给原生小程序使用的自定义 API;
- 注册给小程序中 WebView 组件加载的 H5 使用的自定义 API。
# 1. 自定义小程序API
注册自定义小程序api以及使用自定义小程序api有四步:
- 1.实现自定义api
- 2.注册自定义api
- 3.在小程序配置中声明自定义api
- 4.小程序中调用自定义api
# 1.1 注册自定义小程序异步API
支持的app类型
小程序✅ 小游戏✅ H5应用✅
1)实现自定义异步api。
# 实现自定义小程序异步api示例
public class CustomApi extends BaseApi {
public CustomApi(Context context) {
super(context);
}
@Override
public String[] apis() {
return new String[]{"finclipLogin"}; //api名称
}
@Override
public void invoke(String event, JSONObject param, ICallback callback) {
if ("finclipLogin".equals(event)) {
val result = JSONObject(); // 模拟获取登录token等信息
if (result) {
callback.onSuccess(result)
return;
}
callback.onFail();
}
}
}
2)将其注册到extensionApiManager
中,支持单个注册和批量注册。
注册单个自定义api
批量注册自定义api
3)在小程序配置文件中声明自定义api。
在小程序根目录创建 FinClipConf.js
并进行相应的自定义api配置,或通过 loadExtApi 传入配置参数
module.exports = {
extApi:[
{ //普通交互API
name: 'finclipLogin', //扩展api名 该api必须Native方实现了
sync: false, //是否为同步api
params: { //扩展api 的参数格式,可以只列必须的属性
url: ''
}
},
{
name: 'finclipTestSync',
sync: true, // 是否为同步api
params: {
name:'',
title:''
}
}
]
}
小程序端更多配置信息可参考 ft.loadExtApi
4)小程序里调用自定义小程序异步api
ft.finclipLogin({
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);
}
});
注册自定义api(打开原生页面) 比如,注册自定义api 打开支付页面,支付完毕后,再将结果返回。
首先,实现一个要打开的Activity。(假设所有的支付逻辑都在这个activity)
public class FinClipPayActivity extends AppCompatActivity {
public static final String PAY_RESULT = "pay_result";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fin_clip_pay);
findViewById(R.id.fab).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(FinClipPayActivity.this, getString(R.string.fin_clip_input_content_hint), Toast.LENGTH_SHORT).show();
JSONObject payResult = new JSONObject(); // 模拟支付返回结果
// 将结果回传,并关闭支付页面
String jsonString = payResult.toString();
Intent intent = new Intent();
intent.putExtra(PAY_RESULT, jsonString);
setResult(RESULT_OK, intent);
finish();
}
});
}
}
然后,注册自定义api。
public class CustomApi extends BaseApi {
public CustomApi(Context context) {
super(context);
}
@Override
public String[] apis() {
return new String[]{"finclipPay"}; //api名称
}
@Override
public void invoke(String event, JSONObject param, ICallback callback) {
Intent intent = new Intent();
intent.setClass(mContext, FinClipPayActivity.class);
String jsonString = param.toString();
intent.putExtra("jsonString", jsonString);
callback.startActivityForResult(intent, 100);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data, ICallback callback) {
if (requestCode == 100) {
if (resultCode == RESULT_OK && data != null) {
String jsonString = data.getStringExtra(EXTRA_PAY_RESULT);
try {
JSONObject jsonObject = new JSONObject(jsonString);
callback.onSuccess(jsonObject);
} catch (JSONException e) {
e.printStackTrace();
callback.onFail();
}
} else {
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("errMsg", "支付失败");
callback.onFail(jsonObject);
} catch (JSONException e) {
e.printStackTrace();
callback.onFail();
}
}
}
}
}
再注册自定义api。
FinAppClient.INSTANCE.getExtensionApiManager().registerApi(new CustomApi(this));
在小程序
的根目录下创建FinClipConf.js
,内容示例如下:
module.exports = {
extApi:[
{ //支付API
name: 'finclipPay', //扩展api名 该api必须Native方实现了
sync: false, //是否为同步api
params: { //扩展api 的参数格式,可以只列必须的属性
name: '',
price:'',
}
}
]
}
在小程序中调用自定义api即可。
ft.finclipPay({
name:'赛罗-奥特曼',
price:26.2,
success: function (res) {
console.log("调用支付 success");
console.log(res);
},
fail: function (res) {
console.log("调用支付 fail");
console.log(res);
}
});
# 1.2 注册自定义小程序同步API
支持的app类型
小程序✅ 小游戏✅ H5应用✅
同步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
在小程序进程自定义同步API中,有两种方式获取小程序Activity:
- 外部传入,在自定义API类的构造方法中传入;
- 直接获取,可以通过
FinAppProcessClient.appletProcessActivity
获取当前小程序进程对应的Activity。
3)在小程序配置文件中声明自定义api。
在小程序根目录创建 FinClipConf.js
并进行相应的自定义api配置,或通过 loadExtApi 传入配置参数
小程序端更多配置信息可参考 ft.loadExtApi
module.exports = {
extApi:[
{ //普通交互API
name: 'finclipLogin', //扩展api名 该api必须Native方实现了
sync: false, //是否为同步api
params: { //扩展api 的参数格式,可以只列必须的属性
url: ''
}
},
{
name: 'finclipTestSync',
sync: true, // 是否为同步api
params: {
name:'',
title:''
}
}
]
}
4)小程序里调用
const res = ft.finclipTestSync({'name':'张三', 'title':'Finclip'});
console.log(res.title);
# 1.3 注册(含自定义sope权限的)自定义api
支持的app类型
小程序✅ 小游戏✅ H5应用🚫
# 1.4 获取所有已注册的自定义小程序API
# API
/**
* 获取所有已注册的小程序API
*/
fun getRegisteredApis(): Map<String, IApi>
# 调用示例
# 2. 自定义 WebView 组件API
支持的app类型
小程序✅ 小游戏🚫 H5应用🚫
小程序里加载的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
批量注册自定义api
3)在H5内调用自定义api
在H5内引用我们的桥接JSSDK文件,即可调用上面的注册的方法了。
HTML内调用注册的方法示例:
window.ft.miniProgram.callNativeAPI('js2AppFunction', {name:'getLocation'}, (result) => {
console.log(result)
});
# 2.2 取消注册 WebView 组件API
支持单个取消注册和批量取消注册。
取消单个WebView 组件API
# 调用示例
批量取消WebView 组件API
# 2.3 获取所有已注册的小程序 WebView API
支持的app类型
小程序✅ 小游戏🚫 H5应用🚫
# API
/**
* 获取所有已注册的网页调用的原生API
*/
fun getRegisteredApis(): Map<String, IApi>
# 调用示例
# 3. 在小程序进程中注册api
支持的app类型
小程序✅ 小游戏✅ H5应用✅
正常情况下注册到小程序的api是在主进程调用执行的,当有需要在小程序进程执行的api的时候,需要调用另外的接口去注册。
# 4. 原生调用 JS API
支持的app类型
小程序✅ 小游戏🚫 H5应用🚫
# 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?>)
# 调用示例
首先,在H5内引用我们的桥接JSSDK文件。
然后,在HTML里注册好方法,比如方法名叫app2jsFunction
。
window.ft.onNativeAPIHandler('app2jsFunction', function(res) {
// app2jsFunction callback
})
# 5. 注册原生组件
支持的app类型
小程序✅ 小游戏🚫 H5应用🚫
由于资源有限,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("native-view", TestNativeView::class.java)
最后,小程序里使用自定义组件即可。
<native-view type="native-view" style="left: 0px; top: 0px; width: 100px; height: 100px;">123</native-view>