首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >如何在小程序中引入自有 API?

如何在小程序中引入自有 API?

原创
作者头像
海岛船长加西亚
发布2022-03-24 14:49:27
发布2022-03-24 14:49:27
1.3K0
举报

什么是自定义 API 及其有何作用

自定义 API,顾名思义为开发者为满足自身需求而自己创建的一个 API。那么自己创建的这个 API 能起到什么效果和作用呢。

如果小程序里需要调用一些宿主 App 提供的能力,而 FinClip SDK 未实现或无法实现时,就可以注册一些自定义 API。然后小程序里就可以像调用其他 API 一样调用注册的 API 了。

简单来说这个自定义 API 能起到小程序或者 H5 与原生 App 的交互作用。

注册自定义 API 分两个场景:

  1. 注册给原生小程序使用的自定义 API;
  2. 注册给小程序中 Web-view 组件加载的 H5 使用的自定义 API。

如何注册及使用 FinClip 小程序自定义 API

1. iOS 端注册小程序自定义 API

注册自定义的小程序 API 的函数如下所示:

代码语言:javascript
复制
/**
 注册扩展Api
 
 @param extApiName 扩展的api名称
 @param handler 回调
 @return 返回注册结果
 */
- (BOOL)registerExtensionApi:(NSString *)extApiName handle:(void (^)(id param, FATExtensionApiCallback callback))handler;

比如,我这里注册一个小程序 APIcustomEvent:

代码语言:javascript
复制
[[FATClient sharedClient] registerExtensionApi:@"customEvent" handle:^(id param, FATExtensionApiCallback callback) {
    // xxxx
    callback(FATExtensionCodeSuccess, nil);
}];

然后,在小程序的根目录创建 FinClipConf.js 文件,配置实例如下:

代码语言:javascript
复制
module.exports = {
  extApi:[
    { //普通交互API
      name: 'customEvent', //扩展api名 该api必须Native方实现了
      params: { //扩展api 的参数格式,可以只列必须的属性
        url: ''
      }
    }
  ]
}

extApi 是个数组,所以,您可以注册多个自定义API。

最后,在小程序里调用自定义的 API,示例代码:

代码语言:javascript
复制
ft.customEvent({
    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);
    }
});

2. iOS 端注册小程序 web-view 组件 API

小程序里加载的 H5,如果也想调用宿主 API 的某个能力,就可以利用该方法注册一个 API。

代码语言:javascript
复制
/// 为HTML 注册要调用的原生 api
/// @param webApiName 原生api名字
/// @param handler 回调
- (BOOL)fat_registerWebApi:(NSString *)webApiName handle:(void (^)(id param, FATExtensionApiCallback callback))handler;

我这里为小程序里的 H5 注册了一个叫 js2AppFunction 的方法:

代码语言:javascript
复制
 [[FATClient sharedClient] fat_registerWebApi:@"js2AppFunction" handle:^(id param, FATExtensionApiCallback callback) {
        NSString *name = param[@"name"];
//        id params = param[@"data"];
        if ([name isEqualToString:@"getLocation"]) {
            // 执行定位逻辑
            
            // 返回结果给HTML
            NSDictionary *dict = @{@"errno":@"403", @"errmsg":@"无权限", @"result": @{@"address":@"广东省深圳市南山区航天科技广场"}};
            callback(FATExtensionCodeSuccess, dict);
        } else if ([name isEqualToString:@"getColor"]) {
            // 执行其他逻辑
            
            // 返回结果给HTML
            NSDictionary *dict = @{@"r":@"110",@"g":@"150",@"b":@"150"};
            callback(FATExtensionCodeSuccess, dict);
        }
    }];

在 H5 内引用我们的桥接 JSSDK 文件,即可调用上面的注册的方法了。

HTML 内调用注册的方法示例:

代码语言:javascript
复制
window.ft.miniProgram.callNativeAPI('js2AppFunction', {name:'getLocation'}, (result) => {
    console.log(result)
});
3. Android 端注册小程序自定义API

自定义 API 示例:

代码语言:javascript
复制
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) {
        // 调用方法时原生对应的操作
    }
}

然后将其注册到 extensionApiManager 中,支持单个注册和批量注册。

Kotlin

单个注册

代码语言:javascript
复制
FinAppClient.extensionApiManager.registerApi(CustomApi(this)) 

批量注册

代码语言:javascript
复制
val apis = listOf<IApi>(CustomApi1(), CustomApi2(), CustomApi3())
FinAppClient.extensionApiManager.registerApis(apis) 

Java

单个注册

代码语言:javascript
复制
FinAppClient.INSTANCE.getExtensionApiManager().registerApi(new CustomApi(this)); 

批量注册

代码语言:javascript
复制
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); 

然后,在小程序的根目录创建 FinClipConf.js 文件,配置实例如下:

代码语言:javascript
复制
module.exports = {
  extApi:[
    { //普通交互API
      name: 'customEvent', //扩展api名 该api必须Native方实现了
      params: { //扩展api 的参数格式,可以只列必须的属性
        url: ''
      }
    },
    {
        name: 'customEvent1',
        params: {
            foo: ''
        }
    },
    {
        // foo
    }
  ]
}

最后,在小程序里调用自定义的 API,示例代码:

代码语言:javascript
复制
ft.customEvent({
    url:'https://www.xxx.com',
    success: function (res) {
        console.log("customEvent call succeeded");
        console.log(res)
    },
    fail: function (res) {
        console.log("customEvent call failed");
        console.log(res)
    }
})
4. Android 端注册小程序 web-view 组件 API

小程序里加载的 H5,如果也想调用宿主 API 的某个能力,就可以利用该方法注册一个 API。

代码语言:javascript
复制
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 中,同样也支持单个注册和批量注册。

Kotlin

单个注册

代码语言:javascript
复制
FinAppClient.extensionWebApiManager.registerApi(WebApi(this)) 

批量注册

代码语言:javascript
复制
val apis = listOf<IApi>(WebApi1(), WebApi2(), WebApi3())
FinAppClient.extensionWebApiManager.registerApis(apis)

Java

单个注册

代码语言:javascript
复制
FinAppClient.INSTANCE.getExtensionWebApiManager().registerApi(new WebApi(this)); 

批量注册

代码语言:javascript
复制
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); 

在 H5 内引用我们的桥接 JSSDK 文件,即可调用上面的注册的方法了。

HTML 内调用注册的方法示例:

代码语言:javascript
复制
window.ft.miniProgram.callNativeAPI('js2AppFunction', {name:'getLocation'}, (result) => {
    console.log(result)
});

FinClip 小程序自定义 API 常见问题

1. 为什么注册的自定义小程序 API 不起作用

在注册自定义 API 时,会判断当前的小程序 SDK 是否初始化成功了。如果没有初始化成功,那么注册自定义 API 就不会成功。

所以,注册自定义 API 前,一定要保证小程序已经初始化成功了。

2. 在 FinClip FIDE 中如何 mock 使用自定义 API

在 FIDE 中,有 mock 功能可以方便开发者在开发的途中 mock 模拟自定义 API 的返回结果。如下图:

在 mock 中定义 API 接口字段及返回结果(需要注意的是,这里的 JSON 数据包的返回结果需要的是双引号"")然后在小程序根目录下。

然后,在小程序的根目录创建 FinClipConf.js 文件,配置实例如下:

代码语言:javascript
复制
module.exports = {
  extApi: [{
    name: 'kkshy',
  }]
}

最后就是小程序中的调用

代码语言:javascript
复制
ft.kkshy({
      success: function(res) {
        console.log("success");
        console.log(res);
      },
      fail: function(res) {
        console.log("fail");
        console.log(res);
      }
    });

3. 使用 Flutter 接入的话,自定义 API 是否支持通过 Success 方法接收 Flutter 的回调数据

答案是支持的。

代码语言:javascript
复制
typedef ExtensionApiHandler = Future Function(dynamic params)

自定义的方法返回的结果会返回给小程序

4. 在自定义接口的 invoke() 方法中跳转到宿主 App 的其它页面,做完一系列操作之后,按系统返回键想返回小程序,结果却返回到了宿主 App 中启动小程序的页面,为什么?

原因:

跳转到宿主App其它页面这一步,是通过宿主App中的Context实例来启动Activity的,并且没有把Activity压入新的任务栈中。

Android小程序SDK是多进程架构的,小程序和宿主App处于不同进程中,所处的任务栈自然也是不同的。小程序跳转到宿主App的页面,新打开的页面是添加到宿主App原有的任务栈中的,当从页面返回时,执行的逻辑是在原生App中原有的任务栈中弹出页面,因此会看到原生App的页面被逐个关闭,最后返回到原生应用启动小程序的页面,并没有返回小程序。

解决方案共有 2 种:

方案 1(推荐):

通过 ICallback 的 startActivity 或 startActivityForResult 来跳转到宿主 App 的其它页面。

这是推荐的方案,因为这样做是在小程序所在的任务栈打开新宿主 App 的 Activity 的,Activity 的入栈出栈都是在同一个任务栈中完成的,没有任务栈切换的过程。

更重要的一个原因是:如果需要通过 startActivityForResult 来启动 Activity 并在页面返回时获取到回传的数据,只有使用这种方案,自定义接口的 onActivityResult 才会执行,才能拿到返回的数据。

此方案使用示例:

代码语言:javascript
复制
@Override
public void invoke(String event, JSONObject param, ICallback callback) {
    Intent intent = new Intent();
    intent.setClass(mContext, SecondActivity.class);
    callback.startActivityForResult(intent, 100);
}

方案 2(不推荐):

如果一定要使用宿主 App 中的 Context实例来启动 Activity,就需要对启动原生页面的 Intent 设置"支持多任务栈"和“开启新任务栈”的 Flag,这样可以在原生 App 的进程中新开一个任务栈,开启新任务栈之后,新打开的页面将被逐个压入这个新任务栈中,当结束完原生页面的所有操作之后逐个页面返回时,便会从这个新任务栈中将页面逐个弹出,当这个新任务栈中的所有页面都被弹出后,便会回到小程序进程的任务栈。

因此,在自定义接口的 invoke() 方法中,如果需要跳转到原生应用的其它页面执行某些操作,并期望当关闭这些原生页面后能够返回小程序,那么建议在执行跳转的时候为 Intent 对象同时增加 Intent.FLAG_ACTIVITY_MULTIPLE_TASK 和 FLAG_ACTIVITY_NEW_TASK,如下:

代码语言:javascript
复制
Intent intent = new Intent();
intent.setClass(context, SecondActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent); // context是宿主App中的Context实例

使用此方案,如果通过 startActivityForResult 来启动 Activity,当页面返回时,自定义接口的 onActivityResult 不会被调用,因此不推荐。

5. Taro 中如何给打包后文件添加 FinChatConf.js

taro中可以使用 copy配置项,将 FinChatConf.js 复制到打包后的文件之中,具体写法可参考如下:

代码语言:javascript
复制
module.exports = {
  // ...
  copy: {
    patterns: [
      { from: 'FinChatConf.js', to: 'dist/FinChatConf.js' } // 指定需要 copy 的文件
    ]
  }
}

具体可参考 taro 文档http://taro-docs.jd.com/taro/docs/config-detail#copy

FinClip 小程序自定义 API 示例

自定义 API 相关示例代码可见:https://github.com/finogeeks/auth_demo_android

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是自定义 API 及其有何作用
  • 如何注册及使用 FinClip 小程序自定义 API
    • 1. iOS 端注册小程序自定义 API
    • 2. iOS 端注册小程序 web-view 组件 API
  • FinClip 小程序自定义 API 常见问题
    • 1. 为什么注册的自定义小程序 API 不起作用
    • 2. 在 FinClip FIDE 中如何 mock 使用自定义 API
    • 3. 使用 Flutter 接入的话,自定义 API 是否支持通过 Success 方法接收 Flutter 的回调数据
    • 4. 在自定义接口的 invoke() 方法中跳转到宿主 App 的其它页面,做完一系列操作之后,按系统返回键想返回小程序,结果却返回到了宿主 App 中启动小程序的页面,为什么?
    • 5. Taro 中如何给打包后文件添加 FinChatConf.js
  • FinClip 小程序自定义 API 示例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档