至此,我们完成了插件的使用,整个过程我们都是在 HBuilder X 中进行,接下来我们进入开发插件阶段。
概述
uni-app原生插件是基于开源项目 weex 的 0.26.0 版本架构的扩展机制,同样支持Module(非UI控件)和Component(原生UI控件)两种扩展类型,因此可以非常方便的将weex扩展插件移植到uni-app原生插件中。 在uni-app中支持vue和nvue两种页面,vue页面是基于小程序引擎渲染,nvue页面是基于weex引擎渲染。
vue页面中仅支持使用Module类型uni-app原生插件,不支持调用同步方法返回数据
nvue页面中支持使用Module和Component类型uni-app原生插件
参考下面两个个官方文档,完成基础的开发环境准备:
uni-app原生插件(native plugin)开发指南:https://ask.dcloud.net.cn/article/35428
环境准备
iOS uni-app原生插件开发文档 1.2 文档如下:
在您阅读此文档时,首先要知道 uni-app 支持 weex 插件,同时我们假定您已经具备了相应 iOS 应用开发经验,学习过 weex 知识并能够理解相关概念。此外,您也应该对 HTML , JavaScript , CSS 等有一定的了解,并且熟悉在JavaScript 和 Objective-C 环境下的 JSON 格式数据操作等。
开发前准备:
- OS X 10.14.0+
- Xcode 11.0+
- 学习 weex 0.26.0 版本框架 API,weex扩展API for iOS
- 下载开发插件需要的 SDK 包 最新版本的SDK包,找到里面的 HBuilder-uniPluginDemo 文件夹,里面包含 HBuilder-uniPlugin 插件开发工程,后面会用到( 本文使用 iOSSDK@2.4.6.71959_20191210 )
- 下载开发插件时会用到的 js 代码的开发工具 HBuilderX(下载地址),下载哪个版本的 HBuilderX 需要注意下,保持和上条中提到的 SDK 包(在下载 SDK 包的下载界面中有版本相关的文字描述如下图),它提到的版本号一致(HBuilderX 版本 2.5.1.20200103 )
- 确定 SDK 包里的 Xcode 工程 HBuilder-uniPlugin 内是否引用了 SDK 包里的 liblibWeex.a 库和 weex-main-jsfm.js 文件
- 更新 uni-app 离线打包支持,需要使用 HBuilderX (2.4.6.20191210) 版本生成本地打包 APP 资源
在官方文档中,讲到需要我们 学习 weex 0.26.0 版本框架 API,本文档中可以省略掉,和 weex 相关的细节后面会讲到,不用系统去学习。
插件开发过程梳理(个人认为很重要,但是官方文档里面没有)
最新版本的 SDK 是个什么东西?
从官方提供的链接下载 SDK,下载之后解压出来是这么一个文件夹 ,iOSSDK@2.4.6.71959_20191210
,命令中包含了版本号和 release 日期,我们打开看一下其中内容。
开发原生插件,我们只需要关注 HBuilder-uniPluginDemo 这个文件夹即可,其余的先不管。
HBuilder-uniPluginDemo 文件夹中包含的是一个 xcode 工程,打开工程,我们发现其结构如下。
这张图 hin 重要,这张图从终端视角,展示了 uni-app 是怎样跑起来的。展示了我们写的 js 代码和我们 原生插件是如何产生联系的。
其中,www 文件夹下的资源,是在 HBuilder 中打包生成的,打包入口如下。
有了这个前置知识之后,我们再画个图,从 APP 这个宏观角度来理解一下 uni-app 开发 和 原生插件开发 这两个过程。
uni-app 开发 就是在 HBuilder 中用 js 写页面和逻辑,原生插件以 framework 的方式提供,在 js 中按照某种规范引用(前面的文章中,有讲到如何引用插件市场的原生插件,今天开发调试的时候,我们会讲如何引用本地插件)。
原生插件开发 就是在 xcode 中用 oc 写 framework,调试 framework 的时候,我们使用 www 文件下的资源模拟 js 调用。
uni-app原生插件开发(xcode 侧)
iOS平台uni-app原生插件开发文档 文档中介绍的是制作 .a 静态库,本文制作的是一个 .framework 静态库,接下来主要介绍如何在 uni-app 中基于 WeexSDK 开发 iOS 原生插件。
制作 framework
新建一个 framework 项目。
新建 framework 工程并进行相关配置
新建一个名称为 WBOCRUniSDK
的 framework 工程,xcode11 中,默认创建的是一个动态库,我们将其改为静态库。
在下载的工程包 iOSSDK@2.4.6.71959_20191210 里找到 HBuilder-uniPluginDemo 文件夹,然后打开 HBuilder-uniPlugin工程,把刚创建的静态库工程引入到 HBuilder-uniPlugin 工程。
SDK 支持的最低 iOS 版本为 iOS 9.0,修改 iOS Deployment Target 为 9.0。
然后,在静态库工程 WBWeexOCRSDK
的 Header Search Paths 中添加引用 "$(SRCROOT)/../../SDK/inc" ,做这一步的目的,就是为了引入 weex SDK的一些依赖(注意:后面要选择 recursive,否则会报 'WXModuleProtocol.h' file not found 的错误!)
。
如下图所示:
然后,在 HBuilder-uniPlugin 工程的Link Binary With Libraries中添加 WBWeexOCRSDK.framework 库;然后,在 Target Dependencies 中,添加插件工程的 WBWeexOCRSDK 的 targets,如下图所示:
配置需要注册的插件
打开 HBuilder-uniPlugin 工程里的 info.plist 文件 加入节点,需要严格按要求配置,如下图所示:
其中,hooksClass 的值是类名,是给有些插件需要在 app 启动时做初始化或者获取系统事件用的,如果没有可以不填为空;
plugins 下的每一项是 weex 扩展模块或组件能力相关的配置信息,里面包含name(填weex模块或组件类名对应的js层用到的字符串, js层中将通过该字符串来使用原生层的模块或组件),class(填weex模块或组件类名),type(填module或component,一定不能配置错),注意不支持 weex 的 handler 扩展。
至此,xcode 侧的配置就完成了。
uni-app原生插件开发(HBuilder 侧)
我们在 uni-app 中写一个页面,页面上有调用原生 SDK 的方法。
具体一点,如下图所示:
我在 HBuilder 中,写一个页面页面上有三个按钮,分别调起三个原生接口(获取签名、启动 OCR 、和启动刷脸),底部展示原生接口的回调信息,默认展示"Result"。
写 UI 和调用原生接口的代码,都在 index.vue 中编写。
我先写一个包含 三个 按钮的的 页面,并且给三个按钮分别设置click 方法。
<template>
<view class="content">
<image class="logo" src="/static/logo.png"></image>
<view class="text-area">
<text class="title">{{title}}</text>
</view>
<button class="button" @click="getWBSign">获取 OCR 签名</button>
<button class="button" @click="ocr">启动 OCR</button>
<button class="button" @click="face">启动 刷脸</button>
<text class="result">{{result}}</text>
</view>
</template>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
.button {
display: flex;
justify-content: center;
}
.result {
margin-left: auto;
margin-right: auto;
font-size: 22rpx;
}
</style>
接下来,需要在按钮点击之后调起 原生插件。在上面 xcode 配置中,我即将开发的原生插件命名为 WB-OCRSDK
,所以引用插件的方法为:
const plugin = uni.requireNativePlugin('WB-OCRSDK');
引用插件之后,我需要调用获取签名、OCR 和 刷脸三个方法,目前在 xcode 中还没有开发,我预先给他们命名:
getWBSign() {
// 获取签名
ocr.getDebugParam({
appId: xxx,
orderNO: xxx,
}, result => {
console.log("【uni log】getDebugParam callback ================> result.");
console.log(result);
});
},
ocr() {
// 启动 OCR
ocr.startOCR({
version : xxxx,
appId : xxxx,
nonce : xxxx,
userId : xxxx,
sign : xxxx,
orderNo : xxxx,
config: {
"SDKType": 2,
"needBothSidesRecognized":true
}
}, result => {
console.log("【uni log】startOCR callback ================> result.");
});
},
face() {
// 启动 刷脸
ocr.startFace({
version : xxx,
appId : xxx,
nonce : xxx,
userId : xxx,
sign : xxx,
orderNo : xxx
}, result => {
console.log("【uni log】startFace callback ================> result.");
});
}
以获取签名为例,来说明。
ocr.getDebugParam({
appId: xxx,
orderNO: xxx,
}, result => {
console.log("【uni log】getDebugParam callback ================> result.");
console.log(result);
});
我在插件中必须实现一个 getDebugParam:callback:
方法,js 传递参数给原生代码,原生代码提供一个回调 callback,将结果回传给 js。
其余两个接口套路一样。
至此,js 端的接口写好,我们把 js 打包成资源文件,然后将其复制到 xcode 项目下的 www 文件夹下去。
js 代码如何调用 framework
按照官方文档,新建一个 WBOCRSDKModule
类。
在 .m 中添加
WX_EXPORT_METHOD
代码,添加完成之后,js 就可以透过 weex 来调用我们原生代码了。
实现这几个方法。
@implementation WBOCRSDKModule
WX_EXPORT_METHOD(@selector(startFace:callback:))
WX_EXPORT_METHOD(@selector(startOCR:callback:))
WX_EXPORT_METHOD(@selector(getDebugParam:callback:))
#pragma mark - Export Method
- (void)getDebugParam:(NSDictionary *)options callback:(WXModuleCallback)callback
{
/// 模拟拉取签名地址,合作方接入时,找自己后台拉取
}
- (void)startOCR:(NSDictionary *)options callback:(WXModuleCallback)callback
{
NSLog(@"%s",__func__);
NSLog(@"%@",options);
}
- (void)startFace:(NSDictionary *)options callback:(WXModuleCallback)callback
{
NSLog(@"%s",__func__);
NSLog(@"%@",options);
}
@end
至此,走通了 js 调用 oc 的流程,接下来需要做的事儿就是填充业务代码了。