iOS API

优质
小牛编辑
139浏览
2023-12-01

这里介绍 FinClip 小程序 SDK 提供了哪些能力,以及API的详细说明和使用示例。

1. 基础API

1.1 SDK初始化

在使用小程序的API之前,需要先初始化小程序SDK。只有成功初始化之后,才能使用SDK提供的API,否则 API都无法调用。

初始化SDK的API如下:

/// 初始化SDK
/// @param config 配置对象
/// @param error 初始化失败时返回的error
- (BOOL)initWithConfig:(FATConfig *)config error:(NSError **)error;

/// 初始化SDK
/// @param config 配置对象
/// @param uiConfig UI配置对象
/// @param error 初始化失败时返回的error
- (BOOL)initWithConfig:(FATConfig *)config uiConfig:(FATUIConfig *)uiConfig error:(NSError **)error;

初始化示例:

NSString *appKey = @"这里填上的SDK Key";
FATConfig *config = [FATConfig configWithAppSecret:@"这里填上SDK secret" appKey:appKey];
config.apiServer = @"https://api.finclip.com";
config.apiPrefix = @"/api/v1/mop";
    
[[FATClient sharedClient] initWithConfig:config error:nil];

注意

  1. 从2.13.109版本开始,FinClip SDK 支持配置多个服务器信息,可以同时打开多个不同服务器上的小程序,所以我们提供了配置多个服务器信息的方式。
  2. 以appSecret和appKey构造FATConfig的方法未来可能会弃用,请尽早更新为多服务器的方式。
NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"servers" ofType:@"plist"];
NSArray *array = [NSArray arrayWithContentsOfFile:plistPath];
NSMutableArray *storeArrayM = [NSMutableArray array];
for (NSDictionary *dict in array) {
    FATStoreConfig *storeConfig = [[FATStoreConfig alloc] init];
    storeConfig.sdkKey = dict[@"sdkKey"];
    storeConfig.sdkSecret = dict[@"sdkSecret"];
    storeConfig.apiServer = dict[@"apiServer"];
    storeConfig.apiPrefix = dict[@"apiPrefix"];
    storeConfig.apmServer = dict[@"apmServer"];
    if ([@"SM" isEqualToString:dict[@"cryptType"]]) {
        storeConfig.cryptType = FATApiCryptTypeSM;
    } else {
        storeConfig.cryptType = FATApiCryptTypeMD5;
    }
    
    [storeArrayM addObject:storeConfig];
}
FATConfig *config = [FATConfig configWithStoreConfigs:storeArrayM];
[[FATClient sharedClient] initWithConfig:config error:nil];

FATConfig中的配置项:

配置名称配置描述
appKeySDK Key,校验失败时无法使用SDK (将要弃用)
appSecretSDK secret (将要弃用)
apiServer服务器地址 (将要弃用)
apmServerapm统计的服务器地址 (将要弃用)
apiPrefixapi的版本 (将要弃用)
cryptTypeSDK与后台交互的数据加密方式 (将要弃用)
fingerprintSDK指纹,证联服务器时必填(将要弃用)
currentUserId当前用户唯一标识,小程序缓存信息会存储在以userId命名的不同目录下
disableAuthorize是否禁止SDK触发权限申请,默认为NO,如果设置为YES,则SDK内使用权限的api,不会主动申请权限。
disableGetSuperviseInfo是否禁用SDK的监管接口API,默认为NO,如果设置为YES,则SDK禁用监管接口API(getSuperviseInfo)
appletIntervalUpdateLimit后台自动检查更新的小程序个数,取值范围:0~50。0代表不检查更新;不设置默认是3。
startCrashProtection是否开启Crash防崩溃。UnrecognizedSelector、KVO、Notification、Timer、Container(数组越界,字典插入nil等)、String (越界、nil等)
enableApmDataCompressionapm数据上报时,是否压缩数据
encryptServerData平台接口返回的数据是否要加密

FATUIConfig中的配置项:

配置名称配置描述
navigationTitleTextAttributes导航栏标题的样式,目前仅支持字体的配置。
capsuleConfig右上角胶囊的样式配置,具体参数见FATCapsuleConfig表
progressBarColor小程序中的web-view组件加载链接时的进度条颜色
moreMenuStyle胶囊里更多按钮弹出的菜单视图的样式
hideForwardMenu是否隐藏更多菜单中的转发按钮。
hideFeedbackMenu是否隐藏更多菜单中的投诉反馈按钮。
hideBackToHome是否隐藏更多菜单中的回到首页按钮。
autoAdaptDarkMode是否适配暗黑模式。
appendingCustomUserAgent您需要添加至userAgent中的内容。
appletText默认为“小程序”,您需要替换展示的名称。比如设置会"轻应用",所有显示"小程序"的地方,都会变为"轻应用"
hideTransitionCloseButton是否隐藏转场页的关闭按钮。默认为NO
disableSlideCloseAppletGesture是否禁用侧滑关闭小程序的手势。默认为NO

FATCapsuleConfig(胶囊)中的配置项:

配置名称配置描述
capsuleWidth胶囊的宽度
capsuleHeight胶囊的高度
capsuleRightMargin胶囊的右边框距离屏幕右边框的距离
capsuleCornerRadius胶囊的圆角半径
capsuleBorderWidth胶囊的边框宽度
capsuleBorderLightColor胶囊的浅色边框颜色
capsuleBorderDarkColor胶囊的深色边框颜色
capsuleBgLightColor胶囊的浅色下背景颜色
capsuleBgDarkColor胶囊的深色下背景颜色
moreLightImage胶囊的浅色更多按钮图片
moreDarkImage胶囊的深色更多按钮图片
moreBtnWidth胶囊的更多按钮宽度
moreBtnLeftMargin更多按钮的左边距
closeLightImage胶囊里的深色关闭按钮图片
closeDarkImage胶囊里的深色关闭按钮图片
closeBtnWidth胶囊里关闭按钮的宽度
closeBtnLeftMargin胶囊里关闭按钮的左边距
capsuleDividerLightColor胶囊里浅色分割线颜色
capsuleDividerDarkColor胶囊里的深色分割线颜色

我们的默认胶囊是这样:

那么,我们只需要这样设置,就可以变成圆角:

FATUIConfig *uiConfig = [[FATUIConfig alloc] init];
uiConfig.capsuleConfig.capsuleCornerRadius = 15.5;

效果如下:

1.2 打开小程序

打开小程序,其实是有两个场景:1.普通的打开小程序,这里一般只需要小程序id和服务器地址即可,只能打开上架的线上版本小程序;2.加密信息打开小程序,这个场景是扫描小程序平台上的二维码,得到二维码里的内容,然后使用二维码里的info(即加密信息)打开小程序。

1.2.1 普通打开小程序

打开小程序时,会先判断本地是否有缓存的小程序,如果没有,则会自动从远程服务器上下载小程序,然后打开。如果有缓存的小程序,则会先打开本地小程序,然后在后台校验服务器端是否有新版本。

如果有新版本,则下载新版小程序,下次打开时,就会使用新版小程序;如果没有新版本,则什么也不做。

/// 启动小程序
/// @param request 启动的request
/// @param parentVC 父页面
/// @param completion 完成回调
/// @param closeCompletion 关闭小程序时的回调
- (void)startAppletWithRequest:(FATAppletRequest *)request
        InParentViewController:(UIViewController *)parentVC
                    completion:(void (^)(BOOL result, FATError *error))completion
               closeCompletion:(dispatch_block_t)closeCompletion;

示例代码:

FATAppletRequest *request = [[FATAppletRequest alloc] init];
request.appletId = @"小程序id"; // 必填项
request.apiServer = @"服务器地址"; // 必填项
request.transitionStyle = FATTranstionStyleUp;
request.startParams = startParams;
    
[[FATClient sharedClient] startAppletWithRequest:request InParentViewController:self completion:^(BOOL result, FATError *error) {
    NSLog(@"打开小程序:%@", error);
} closeCompletion:^{
    NSLog(@"关闭小程序");
}];

1.2.2 加密信息打开小程序

这种情况流程一般会复杂一些,需要先扫描小程序平台上的二维码,得到二维码里的内容,然后取二维码里的info(即加密信息)调用该接口打开小程序。

/// 解密信息,并启动小程序
/// @param request 加密信息的request
/// @param parentVC 父页面
/// @param completion 完成回调
/// @param closeCompletion 关闭小程序时的回调
- (void)startAppletWithDecryptRequest:(FATAppletDecryptRequest *)request
               InParentViewController:(UIViewController *)parentVC
                           completion:(void (^)(BOOL result, FATError *error))completion
                      closeCompletion:(dispatch_block_t)closeCompletion;

1.3 关闭小程序

1.3.1 关闭单个小程序

/**
关闭打开的指定小程序
@param animated 是否显示动画
@param completion 关闭完成的回调
*/
- (void)closeApplet:(NSString *)appletId animated:(BOOL)animated completion:(dispatch_block_t)completion;

1.3.2 关闭所有小程序

有些场景下,可能存在A小程序打开B小程序,B小程序打开C小程序的情况,这时想要关闭打开的所有小程序,可以使用该方法。

/**
关闭当前打开的所有小程序
@param completion 关闭完成的回调
*/
- (void)closeAllAppletsWithCompletion:(dispatch_block_t)completion;

1.3.3 关闭当前小程序

/**
关闭当前的小程序
@param animated 是否显示动画
@param completion 关闭完成的回调
*/
- (void)closeCurrentApplet:(BOOL)animated completion:(dispatch_block_t)completion;

1.3.4 其他关闭小程序

以下API都是上述api的旧版本,因为缺少了completion回调,所以未来可能会弃用。

/**
关闭打开的指定小程序
@param animated 是否显示动画
*/
- (void)closeApplet:(NSString *)appletId animated:(BOOL)animated;

/**
关闭当前打开的所有小程序
*/
- (void)closeAllApplets;

/**
关闭当前的小程序
@param animated 是否显示动画
*/
- (void)closeCurrentApplet:(BOOL)animated;

1.4 结束小程序

小程序被关闭后,并没有真的结束,而是在后台挂起。等下次打开小程序时,会立即将小程序切换至前台运行。 所以,如果我们希望小程序关闭后,真的被结束掉,可以根据实际情况调用以下API来结束单个小程序或所有小程序。

1.4.1 结束单个小程序

/**
删除内存中的某个小程序
*/
- (void)clearMemeryApplet:(NSString *)appletId;

1.4.2 结束所有小程序

/**
 清空内存中缓存的小程序数据
 */
- (void)clearMemoryCache;

1.5 删除小程序

由于小程序的运行,会将小程序包和小程序信息缓存在本地,以后打开时速度会非常快。 所以,如果想要将小程序的所有信息都删除,那么可以调用以下api删除某个小程序或者删除所有小程序。

1.5.1 删除单个小程序

/**
 从本地缓存中删除小程序
 
 @param appletId 小程序id
 @return BOOL 结果
 */
- (BOOL)removeAppletFromLocalCache:(NSString *)appletId;

1.5.2 删除所有小程序

///  删除本地缓存的小程序
- (void)clearLocalApplets;

1.6 搜索小程序

要搜索小程序,需要两步:

  1. 确保在初始化SDK的时候,配置了该服务器信息;
  2. 调用该搜索接口搜索小程序
/// 搜索小程序
/// @param request 搜索的request
/// @param completion 搜索结果
- (void)searchAppletsWithRequest:(FATSearchAppletRequest *)request
                      completion:(void (^)(NSDictionary *result, FATError *aError))completion;

搜索小程序的示例:

FATSearchAppletRequest *searchRequest = [[FATSearchAppletRequest alloc] init];
searchRequest.apiServer = @"https://api.finclip.com";
searchRequest.text = @"小程序";
[[FATClient sharedClient] searchAppletsWithRequest:searchRequest completion:^(NSDictionary *result, FATError *aError) {
    NSLog(@"");
}];

1.7 获取小程序对象信息

/// 获取当前正在运行的小程序对象
- (FATAppletInfo *)currentApplet;

1.8 获取小程序当前WebView信息

1.8.1 获取当前webView的URL

如果当前页面加载的不是H5,则会返回nil;如果加载的是H5,则会返回H5对应的NSURL。

/**
获取当前加载H5的URL
如果小程序当前页面加载的不是H5,则返回nil
*/
- (NSURL *)getCurrentWebViewURL;

1.8.2 获取当前webView的UserAgent

/**
获取小程序当前页面webView的userAgent
*/
- (void)getCurrentWebViewUserAgentWithCompletion:(void (^)(NSString *userAgent, NSError * error))completionHandler;

1.9 获取小程序页面截图

注意:这里生成的截图的宽高比是5:4。会从导航栏以下(0,0)绘制开始截取。

/**
 生成当前页面截图
 */
- (UIImage*)getCurrentAppletImage;

1.10 获取使用过的小程序列表

获取打开过的所有小程序列表,已删除的小程序不包含。

/**
 获取本地的小程序
 
 @return 小程序数组<FATAppletInfo>
 */
- (NSArray *)getAppletsFromLocalCache;

1.11 微信小程序二维码信息转换为FinClip小程序

///  解析微信小程序二维码,得到凡泰小程序信息
/// @param qrCode  微信二维码
/// @param apiServer  解析服务器url
/// @param completion 结果回调
- (void)parseAppletInfoFromWXQrCode:(NSString *)qrCode apiServer:(NSString *)apiServer completion:(void (^)(FATAppletSimpleInfo *appInfo, FATError *aError))completion;

该API的使用场景比较特别,当某小程序在微信和FinClip服务上都上架之后,可以在FinClip平台关联微信的小程序。这时FinClip平台上的线上版二维码,既可以用微信扫码打开,也可以用凡泰助手或其他集成了FinClip SDK的APP扫码打开。

流程是先扫描该二维码,得到二维码内容,然后调用该接口获取FinClip 小程序id,最后调用打开小程序的API即可。

1.12 代理方法

小程序的部分功能,需要原生端去实现才能调用,比如转发和获取主体App的用户信息等。

这些代理方法都声明在FATAppletDelegate中

/** 转发事件
 当你点击小程序右上角更多里的转发菜单时,会触发小程序里shareAppMessage方法,然后回调到原生该方法
 @param contentInfo 小程序相关信息,里面包含小程序id、小程序名称、小程序图标、小程序截图(5:4)等。
 {
    appAvatar = "小程序图标地址";
    appDescription = "小程序的描述信息";
    appId = "小程序id";
    appInfo =  {}; // 客户可在appInfo中自定义字段,appInfo内容会透传
    appStartParams =     {
        path = "点击转发时的小程序页面路径";
    };
    appThumbnail = "小程序封面图的路径,可能是网络路径或者本地路径,宽高比是5:4";
    appTitle = "小程序名称";
    userId = "小程序开发者id";
}
 @param completion 执行完后的回调,如果你转发操作执行完后,希望告知小程序端转发结果,就需要调用该block。
 */
- (void)forwardAppletWithInfo:(NSDictionary *)contentInfo completion:(void (^)(FATExtensionCode code, NSDictionary *result))completion;

/// 获取用户信息
/// @param appletInfo 小程序信息
- (NSDictionary *)getUserInfoWithAppletInfo:(FATAppletInfo *)appletInfo;

/// 更多按钮中自定义的菜单,会在页面弹出菜单时调用该api
/// @param appletInfo 小程序信息
/// @param path 页面路径
- (NSArray<id<FATAppletMenuProtocol>> *)customMenusInApplet:(FATAppletInfo *)appletInfo atPath:(NSString *)path;

/// 点击自定义菜单时,会触发的事件
/// @param customMenu 自定义菜单对象
/// @param appletInfo 小程序信息
/// @param path 当前页面路径
- (void)customMenu:(id<FATAppletMenuProtocol>)customMenu inApplet:(FATAppletInfo *)appletInfo didClickAtPath:(NSString *)path;

代理实现示例:

1.在合适的位置赋值实现代理方法的实例对象

[FATClient sharedClient].delegate = [FATClientHelper shareInstance];

2.创建实现代理方法的类

#import <Foundation/Foundation.h>
#import <FinApplet/FinApplet.h>

@interface FATClientHelper : NSObject<FATAppletDelegate>

+ (instancetype)shareInstance;

@end

3.在实现类(比如FATClientHelper)中实现对应的代理方法。

1.13 处理Open URL

/// 处理URL
/// @param URL 具体的URL路由
- (BOOL)handleOpenURL:(NSURL *)URL;

如果希望在Safari浏览器或其他App中打开自己的APP中的小程序,需要实现- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options方法。

示例代码:

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
    if ([[FATClient sharedClient] handleOpenURL:url]) {
        return YES;
    }
    return YES;
}

1.14 处理Universal Link URL

/// 处理Universal Link
/// @param URL Universal Link URL
- (BOOL)handleOpenUniversalLinkURL:(NSURL *)URL;

同上面的handleOpenURL一样,如果想要支持universal link 的方式打开小程序。也得实现- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray<id<UIUserActivityRestoring>> * __nullable restorableObjects))restorationHandler方法。

示例代码:

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
{
    if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
        NSURL *url = userActivity.webpageURL;
        NSLog(@"url = %@",url.absoluteString);
        return [[FATClient sharedClient] handleOpenUniversalLinkURL:url];
    }
    return YES;
}

1.15 保存文件至当前小程序临时目录

SDK支持原生保存文件到小程序的缓存目录,然后返回文件的本地路径,以供小程序使用。

/**
 保存文件到小程序的缓存路径
 
 @param fileData 文件的二进制数据
 @param fileName 文件名,需要保证文件名唯一,否则可能会覆盖
 @return 文件的本地路径,例如:finfile://tmp_fdfdkfjdkfjdkjfdkjf.jgp
 */
- (NSString *)saveFile:(NSData *)fileData fileName:(NSString *)fileName;

1.16 小程序文件路径转换为绝对路径

在有些场景下,我们拿到小程序的文件路径,无法获取到文件数据,这时可以用该方法转换为绝对路径。

比如,在使用小程序的转发功能时,返回的图片路径是小程序文件路径,可以用该方法转换为绝对路径,然后获取到图片数据再去调起第三方分享。 再比如,自定义api里,可以传递小程序文件路径的参数,宿主app用该方法转换为绝对路径后,即可拿到文件数据。

/**
将文件路径转为绝对路径
如果是 网络文件路径,则直接返回。
如果是小程序中的路径,比如finfile://tmp_fdfdkfjdkfjdkjfdkjf.jpg ,则会转为本地绝对路径
如果是小程序包中的文件路径,比如image/xxx.jpg,也会转为绝对路径
其他情况则返回传入的路径

@param path  文件路径
@return 文件的绝对路径
*/
- (NSString *)fat_absolutePathWithPath:(NSString *)path;

2. 高级API

2.1 注册自定义API

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

注册自定义API分两个场景:1.注册给原生小程序使用的自定义API;2.注册给小程序中web-view组件加载的H5使用的自定义API。

2.1.1 注册小程序API

注册自定义的小程序API的函数

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

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

[[FATClient sharedClient] registerExtensionApi:@"customEvent" handle:^(id param, FATExtensionApiCallback callback) {
    // xxxx
    callback(FATExtensionCodeSuccess, nil);
}];

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

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

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

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

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.1.2 注册小程序web-view组件API

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

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

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

    [[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 (opens new window)文件,即可调用上面的注册的方法了。

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

window.FinChatJSBridge.invoke('js2AppFunction', {name:'getLocation'}, (result) => {
    console.log(result)
});

2.2 原生调用JS API

同样的如果宿主App想要调用小程序加载的H5中的某个方法,就可以使用该API。

/// 原生调用HTML中的JS函数
/// @param eventName 函数名
/// @param paramString 函数的参数字典转成的json
/// @param pageId webView ID,可不传,默认调用最顶层页面里H5的函数
/// @param hanler 调用结果回调
- (void)fat_callWebApi:(NSString *)eventName paramString:(NSString *)paramString pageId:(NSNumber *)pageId handler:(void (^)(id result, NSError *error))hanler;

首先,在H5内引用我们的桥接JSSDK (opens new window)文件。

然后,在HTML里注册好方法,比如方法名叫app2jsFunction

window.FinChatJSBridge.webSubscribe('app2jsFunction', function(res) {
    // app2jsFunction callback
})

最后,原生端调用如下API来调用HTML中的JS函数:

NSString *jsonParams = @""; //这里应该是参数字典转换成的json字符串。
NSNumber *pageId = @(1234); //这里是HTML中传过来的pageId
[[FATClient sharedClient] fat_callWebApi:@"app2jsFunction" paramString:jsonParams pageId:pageId handler:^(id result, NSError *error) {
        
}];

2.3 注册原生组件

由于资源有限,livePusher 和livePlayer等原生组件的实现可能需要借助外部的第三方控件,这时候就可以注册原生组件。我们现在支持注册的原生组件有三个:Camera、LivePlayer、LivePusher。

首先,创建组件视图,实现其协议方法。

.h

#import <UIKit/UIKit.h>
#import <FinApplet/FATAppletNativeProtocol.h>

NS_ASSUME_NONNULL_BEGIN

@interface FATNativeView : UIView <FATAppletNativeViewProtocol>
@property (nonatomic, strong) NSNumber *nativeViewId;
@property (nonatomic, strong) NSString *type;

@end

@interface FATNativeCameraView : FATNativeView <FATAppletNativeCameraProtocol>

@end

@interface FATNativeLivePlayerView : FATNativeView <FATAppletNativeLivePlayerProtocol>

@end

@interface FATNativeLivePusherView : FATNativeView <FATAppletNativeLivePusherProtocol>

@end

NS_ASSUME_NONNULL_END

.m

@implementation FATNativeView
+ (UIView *)onCreateView:(NSDictionary *)param {
    return [[self alloc] initWithParam:param];
}

- (instancetype)initWithParam:(NSDictionary *)param {
    CGRect frame = CGRectZero;
    NSDictionary *style = [param objectForKey:@"style"];
    if (style) {
        CGFloat x = [[style objectForKey:@"left"] floatValue];
        CGFloat y = [[style objectForKey:@"top"] floatValue];
        CGFloat height = [[style objectForKey:@"height"] floatValue];
        CGFloat width = [[style objectForKey:@"width"] floatValue];
        frame = CGRectMake(x, y, width, height);
    }
    self = [super initWithFrame:frame];
    if (self) {
        _type = param[@"type"];
        _nativeViewId = param[@"nativeViewId"];
    }
    return self;
}

- (void)onUpdateView:(NSDictionary *)param {
    NSDictionary *style = [param objectForKey:@"style"];
    if (style) {
        CGRect frame = CGRectZero;
        CGFloat x = [[style objectForKey:@"left"] floatValue];
        CGFloat y = [[style objectForKey:@"top"] floatValue];
        CGFloat height = [[style objectForKey:@"height"] floatValue];
        CGFloat width = [[style objectForKey:@"width"] floatValue];
        frame = CGRectMake(x, y, width, height);
        self.frame = frame;
    }
}

- (void)onDestroyView:(NSDictionary *)param {
    NSLog(@"销毁了%@",param);
}


@end


@implementation FATNativeCameraView

- (void)setCameraZoom:(NSDictionary *)param success:(FATNativeCallback)callBack {
    
}

@end

@implementation FATNativeLivePlayerView


@end

@implementation FATNativeLivePusherView


@end

然后,设置组件的视图class

[FATClient sharedClient].nativeViewManager.cameraClass = [FATNativeCameraView class];
[FATClient sharedClient].nativeViewManager.livePlayerClass = [FATNativeLivePlayerView class];
[FATClient sharedClient].nativeViewManager.livePusherClass = [FATNativeLivePusherView class];

原生给nativeView发送消息

[[FATClient sharedClient].nativeViewManager sendEvent:@"eventName" nativeViewId:@(1234) detail:@{} completion:^(id result, NSError *error) {
            
}];

原生给小程序发送全局消息

[[FATClient sharedClient].nativeViewManager sendCustomEventWithDetail:@{} completion:^(id result, NSError *error) {
            
}];

2.4 注册自定义菜单

如果,您想往右上角的更多菜单中添加一些自己业务相关的菜单,那么就可以注入自定义的菜单。

首先,自定义一个FATClientHelper类,实现FATAppletDelegate协议。

#import <Foundation/Foundation.h>
#import <FinApplet/FinApplet.h>

@interface FATClientHelper : NSObject<FATAppletDelegate>

+ (instancetype)shareInstance;

@end

然后,在SDK初始化成功后后,设置SDK的代理为 FATClientHelper 对象。

示例代码

[[FATClient sharedClient] initWithConfig:config error:nil];
[FATClient sharedClient].delegate = [FATClientHelper shareInstance];

最后,在FATClientHelper中实现,如下协议方法:

// 返回要注入的菜单对象,菜单对象是要实现 FATAppletMenuProtocol 协议的
// 菜单对象分为两种类型(默认为Common类型):
// 1.OnMiniProgram类型:需要后台配置+小程序配置,取相同menuId的集合显示
// 2.Common类型:配置则显示
// PS: 这里兼容旧版本,若后台未升级版本,或后台升级版本后未配置,则仅需要适配菜单对象的menuId为NSString类型
- (NSArray<id<FATAppletMenuProtocol>> *)customMenusInApplet:(FATAppletInfo *)appletInfo atPath:(NSString *)path
{
    
    FATCustomMenuModel *favModel1 = [[FATCustomMenuModel alloc] init];
    favModel1.menuId = @"WXShareAPPFriends";
    favModel1.menuTitle = @"微信好友";
    favModel1.menuIconImage = [UIImage imageNamed:@"minipro_list_wx_chat"];
    favModel1.menuType = FATAppletMenuStyleOnMiniProgram;

    FATCustomMenuModel *favModel2 = [[FATCustomMenuModel alloc] init];
    favModel2.menuId = @"WXShareAPPMoments";
    favModel2.menuTitle = @"微信朋友圈";
    favModel2.menuIconImage = [UIImage imageNamed:@"minipro_list_wx_monents"];
    favModel2.menuType = FATAppletMenuStyleOnMiniProgram;

    FATCustomMenuModel *favModel3 = [[FATCustomMenuModel alloc] init];
    favModel3.menuId = @"Restart";
    favModel3.menuTitle = @"重启";
    favModel3.menuIconImage = [UIImage imageNamed:@"minipro_list_restart"];
    favModel3.menuType = FATAppletMenuStyleCommon;

    return @[favModel1, favModel2, favModel3];
}

// 点击自定义菜单时的事件(旧版,后台未升级或升级后未配置菜单时使用)
- (void)customMenu:(id<FATAppletMenuProtocol>)customMenu inApplet:(FATAppletInfo *)appletInfo didClickAtPath:(NSString *)path
{
    NSLog(@"点击了%@",customMenu.menuTitle);
    NSLog(@"path = %@",path);
}

// 点击自定义菜单时的事件(新版,后台与小程序配置时使用)
- (void)clickCustomItemMenuWithInfo:(NSDictionary *)contentInfo completion:(void (^)(FATExtensionCode, NSDictionary *))completion 
{
    /**
    contentInfo 中包含
    {
         @"title": @"标题",
         @"description": @"描述",
         @"imageUrl": @"图片路径",
         @"path": @"点击时的小程序页面路径"",
         @"menuId": @"点击的菜单按钮标识",
         @"params": self.params     // 原始参数数据,由小程序提供
    }
    */
    // 小程序回调调用,通知小程序点击事件处理情况
    completion(FATExtensionCodeSuccess, contentInfo);
}

2.5 隐藏导航栏

如果想要将小程序页面的导航栏完全隐藏,自己实现导航栏,FinClip小程序SDK也是支持的。

像微信、支付宝、百度等小程序的navigationStyledefault/custom两个值,而FinClip小程序SDK在此基础上,新增了一个hide,即有default/custom/hide三个值。

所以在需要隐藏导航栏的页面,设置navigationStyle​hide即可。

2.6 设置灰度发布自定义规则

小程序SDK的FATAppletDelegate中一个协议方法:

- (NSDictionary *)grayExtensionWithAppletId:(NSString *)appletId

实现这个协议方法即可。

示例代码如下:

/// 小程序灰度扩展参数
/// @param appletId 小程序id
- (NSDictionary *)grayExtensionWithAppletId:(NSString *)appletId
{
    NSDictionary *grayExtension = @{@"key1":@"value1"};
//    if ([appletId isEqualToString:@"5e017a61c21ecf0001343e31"]) {
//        grayExtension = @{@"fckey1":@"fcvalue1"};
//    }
    return grayExtension;
}

然后,小程序SDK在加载小程序时,会调用该协议方法获取小程序的灰度扩展参数,透传给后台服务匹配相关规则。

2.7 使用路由的形式打开小程序

有些时候,我们希望能在safari加载的网页里或者其第三方app打开自己app中的小程序,就需要实现对应的配置。

首先,确保集成SDK时,配置了URL Type,就是URL Schemes(fat+sdkKey的md5)那里。

然后,确保实现了handleOpenURL

最后,在H5里调用fat{sdkKey的md5}://applet/appid/{小程序id}

示例:fat705b46f78820c7a8://applet/appid/5e017a61c21ecf0001343e31

您可以在safari浏览器的地址栏中输入完成的url(比如:fat705b46f78820c7a8://applet/appid/5e017a61c21ecf0001343e31),然后回车即可打开您的app,然后打开小程序。

2.8 原生给小程序发送消息

[[FATClient sharedClient].nativeViewManager sendCustomEventWithDetail:@{} completion:^(id result, NSError *error) {    
}];

3. 扩展SDK

扩展SDK 是对核心SDK的补充,所以要使用扩展SDK,也必须依赖核心SDK。 为了保证 SDK 的安全稳定性,将需要权限的API尽可能放到扩展SDK,FinClip 将 SDK 拆分为核心 SDK 与拓展 SDK,后者是前者的补充,因此使用拓展 SDK 也必须依赖核心 SDK。

在拓展 SDK 中,主要包含的功能见 # 3.2 小程序api一览 小节

3.1 注册扩展API

扩展SDK中的API,需要注册,否则小程序中也无法调用扩展SDK中的API。

[[FATExtClient sharedClient] fat_prepareExtensionApis];

3.2 小程序api一览

部分与权限相关的小程序api的是在扩展SDK中实现的,扩展SDK中包含的小程序api如下:

api名称api描述信息
chooseLocation选择位置。
getLocation获取位置信息。
startRecord开始录音。
stopRecord停止录音。
getClipboardData获取剪贴板内容。
setClipboardData设置剪贴板内容。
RecorderManager全局唯一的录音管理器