开发

端能力扩展

1 功能说明

1.1 扩展介绍

宿主方根据自己的业务需求,现有swan core(swan.js)中的端能力不能满足小程序业务时,可能会对其进行功能扩展。扩展分两步工作:

  • 开发前端extension.js(后期可废弃);
  • 开发NA端的对应端能力;

1.2 扩展流程

图片

1.3 协议介绍

小程序中的端能力是通过协议方式进行调起的,对NA组件或模块能力的包装器,具体格式:

1
2

scheme://component/module/action?params=$params&callback=$callback

协议结构:(目前小程序业务component为swanAPI
图片

  • scheme:为宿主方APP的协议头,能通过Custom URL Scheme方式调起宿主APP的scheme;
  • component与module:component表示业务类型标识,小程序标识为swanAPI,module表示模块类型标识,根据module是否需要可分为二级协议、三级协议

    • 二级协议swanAPI/action,没有module
    1
    2
    // API-获取城市省份信息
    baiduboxapp://swanAPI/getRegionData?callback=_bdbox_js_353&upgrade=0&oauthType=swan
    • 三级协议swanAPI/module/action,有module,NA端扩展类名需要与module名字绑定,绑定时注意,module的名字首字母大写。
    1
    2
       // 组件-地图组件remove端能力,module名为"Map",对应扩展类为BBASMMapPlugin
    baiduboxapp://swanAPI/map/remove?params={"mapId":"0","slaveId":"4"}&callback=_bdbox_js_186
  • action:作为path的最后一级,即为端能力的方法。

    1
    2
       // 组件-地图组件remove端能力,action名为"remove",对应扩展类为BBASMMapPlugin的remove方法
    baiduboxapp://swanAPI/map/remove?params={"mapId":"0","slaveId":"4"}&callback=_bdbox_js_186
  • params:传递给业务的参数、二级回调函数cb,params格式为json。

    【注】NA端上的端能力描述(扩展方法前的注释)中”@args”对应params里面的字段,如果有二级回调cb字段,需要在扩展方法中执行二级回调cb方法(调用方式具体参考2.4 实现plugin)。

  • callback:协议中的一级回调函数,端能力调用成功或失败,NA端必须进行回调(调用方式具体参考2.4 实现plugin)。

  • upgrade:当调用协议大于NA支持最大版本号时,”1”提示升级,”0”不提示(可以废弃)。

1.4 扩展分类

扩展端能力根据响应方式分为:同步端能力、异步端能力(大多按照这种方式扩展)。

1.4.1 同步扩展

同步方法命名以”Sync”为后缀,在端能力描述中的”@config”节点”web”值: {“invoke”: “swan.prompt”, “handler”: “bridge”},具体参考BBASMPlugin+System.h文件的”getSystemInfoSync”方法。

1.4.2 异步扩展

异步方法,在端能力描述中”@config”节点”web”值: {“invoke”: “swan.message.url”, “handler”: “bridge”}


2 开发指南

2.1 前端extension.js包集成

按照前端的扩展功能,开发扩展前端能力,生成extension.js(可能还有extension.css)文件,对文件进行zip格式压缩为extension.zip,同时需要一个extension-config.json文件描述extenson包的版本号;宿主工程中需要预置这两个文件;

注:extension.zip包如果包含多个文件,压缩zip包时一定要注意了,在mac上选中多个文件进行压缩成zip文件,如果单独为文件夹压缩,扩展包的路径会找不到,导致扩展的端能力就调不起来。在沙箱里面的extension包的路径为:Documents/SwanCaches/swan-core-extension/preset(或者remote)/1.0.0(版本号)/(包含extension.js、extension.css)

2.2 实现扩展协议接口

需要实现配置中的”Extension配置”接口:(具体实现参考开源工程的SWANPlatformImplement)

2.3 定义plugin

  • 以二级协议形式进行扩展,需要对BBASMPlugin进行类扩展(注:类扩展名务必加上宿主的前缀),moudle名为swanAPI,不需要进plugin注册,内部已注册过swanAPI这个moudle;扩展的分类名:BBASMPlugin+XXX;

  • [注] 以三级协议形式进行扩展,需要继承BBASDPluginBase类,moudle名为component+module,以”Plugin”命名结尾,此时需要进行手动注册plugin类,具体参考2.5 注册plugin; (需要注册扩展plugin类,不然当前会视频播放无法执行)

  • [注] 端能力方法名以协议中的action命名(不区分大小写);同时需要对端能力方法按照规定格式添加端能力描述(必须要加,否则端能力无法调起),端能力描述按照注释方式编写;百度内部可访问小程序端能力开发流程文档

端能力描述模板如下:(在ES平台填写扩展端能力,端能力描述会自动生成,拷贝到NA端对应的端能力方法前)

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 描 述:
* 示 例: 调起协议
* 文 档:
* 备 注:
* ********** description ************
* @name: baidu.action
* @authority: swanAPI
* @path: /taction
* @args: [{"name": "cb", "value": "string"}, {"name": "timeout", "value": "string="}, {"name": "type", "value": {"oneOf": ["weibo", "qq", "weixin", "sms"]}}]
* @config: {"swan": {"web": {"invoke": "swan.message.url", "handler": "bridge"}, "jsc": {"invoke": "swan.method.url", "method": "_naSwan.bridge.postMessage"}}}
*/

比如(二级协议):第三方登录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
协议:baiduboxapp://swanAPI/thirdPartyLogin?params={"cb":"_bdbox_pjs_923","type":"qq"}&callback=__jsna_30

moudle名:swanAPI
plugin类:BBASMPlugin+PrivateLogin

端能力(方法)描述:
/**
* 描 述: 小程序第三方登录能力thirdPartyLogin
* 示 例: baiduboxapp://swanAPI/thirdPartyLogin?params={"cb":"_bdbox_pjs_923","type":"qq"}&callback=__jsna_30
* 文 档: http://ft.baidu.com/#/scheme/swan_thirdpartylogin
* 备 注:
* ********** description ************
* @name: baidu.thirdPartyLogin
* @authority: swanAPI
* @path: /thirdPartyLogin
* @args: [{"name": "cb", "value": "string"}, {"name": "timeout", "value": "string="}, {"name": "type", "value": {"oneOf": ["weibo", "qq", "weixin", "sms"]}}]
* @config: {"swan": {"web": {"invoke": "swan.message.url", "handler": "bridge"}, "jsc": {"invoke": "swan.method.url", "method": "_naSwan.bridge.postMessage"}}}
*/
- (void)pushThread:(BBASchemeDispatcher *)dispatcher;

比如(三级协议):视频播放

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

协议:baiduboxapp://swanAPI/video/play?params={"slaveId":"1","videoId":"1"}&callback=_bdbox_js_186&upgrade=0

moudle名:Video (需要注册扩展plugin类,不然当前会视频播放无法执行)
plugin类:BBASMVideoPlugin,端能力方法为:

端能力(方法)描述:
/**
* 描 述: 小程序视频组件开始播放
* 示 例: baiduboxapp://swanAPI/video/play?params={"slaveId":"1","videoId":"1"}&callback=_bdbox_js_186&upgrade=0
* 文 档: http://ft.baidu.com/#/scheme/swan_video_play
* 备 注:
* ********** description ************
* @name: video.play
* @authority: swanAPI
* @path: /video/play
* @args: [{"name": "videoId", "value": "string"}, {"name": "slaveId", "value": "string"}]
* @config: {"swan": {"web": {"invoke": "swan.message.url", "handler": "bridge"}, "jsc": {"invoke": "swan.method.url", "method": "_naSwan.bridge.postMessage"}}}
*/
- (void)play:(BBASchemeDispatcher *)dispatcher;
  • 端能力中的方法均为对象方法。

2.4 实现plugin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
- (void)play:(BBASchemeDispatcher *)dispatcher {

// 执行一级回调失败:校验协议传递过来的字段非法或某些条件不满足时
{
[dispatcher doCallbackWithStatus:kBBASDCallBackParamsErrorStatus
message:kBBASDCallBackParamsErrorMSG
data:@{一级参数}}];
return;
}

// 执行一级回调成功:参数合法
{
[dispatcher doCallbackWithStatus:kBBASDCallBackSuccessStatus
message:kBBASDCallBackSuccessMSG
data:@{一级参数}];
}

// 执行二级回调:协议里面的params包含有二级回调"cb"
{
// status为1,业务执行失败
{
[dispatcher doCallbackWithJSMethod:cb
data:@{@"status": @"1",
@"message": kBBASDCallBackParamsErrorMSG,
@"data": dataDic}];
}

// status为0,业务执行成功
{
[dispatcher doCallbackWithJSMethod:cb
data:@{@"status": @"0",
@"message": kBBASDCallBackSuccessMSG,
@"data": dataDic}];
}
}

}

2.5 注册plugin

以三级协议形式进行的plugin扩展,是需要手动注册,宿主方需要写一个类实现BBPModuleProtocol协议,同时必须实现- (void)moduleRegister:(BBPContext *)context协议方法,在该方法体中调用registerPluginWithModule(plugin类, moudle名);moudle不能重复注册,一个moudle对应一个具体的plugin类;

比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

// 扩展能力的module,需要在这个类注册;
// BBASMImplementModule.h 文件
@interface BBASMImplementModule : NSObject<BBPModuleProtocol>

@end

-------------------------------------------------------

// BBASMImplementModule.m 文件
ModuleDefine(BBASMImplementModule)
@implementation BBASMImplementModule

- (void)moduleRegister:(BBPContext *)context {
// 注册宿主扩展的端能力,moudle与plugin类一一对应
[self registerPlugin:[BBASMVideoPlugin class] moduleName:@"Video"];
}

2.6 集成端能力描述表

  • 在开源demo中,copy脚本Script/scheme_desc_collector.py到宿主工程的根目录;

  • 在宿主根目录下执行命令python scheme_desc_collector.py,会在该目录下生成BBAPluginDescription.zip文件;

  • 将BBAPluginDescription.zip放在合适的位置,可以根据需要重新命名,并在platform协议中的+ (NSString *)pluginDescriptionPath方法中返回此压缩文件的路径;

2.7 联调plugin

前面所有的工作都做完了,运行宿主APP(真机、模拟器都可以),打开一个小程序,在浏览器的菜单选择“开发”选项,如图:
图片

  • 找到当前小程序的正在运行的salve页面,title名字:世界很复杂,百度更懂你;
  • 在当前页面的控制台下,输入swan.hostName.action(),hostName是extension.js里面module.exports下的name(宿主方的hostName),”baidu”作为手百这边的hostName,action是hostMethodDescriptions节点下的name,比下图为例,要调用NA端的publishThread能力,在控制台上,调用方式:swan.baidu.publishThread(),回车,通过NA端上的BBASchemeDispatcher(有提供源码联调)协议分发,如果找到NA端上的publishThread的方法调用,说明扩展功能已经打通。

图片

2.8 plugin命名规范

  • 建议NA端上扩展的plugin类命名:BBASMXXPlugin;