# iOS API

这里介绍 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;

初始化示例:

FATStoreConfig *storeConfig = [[FATStoreConfig alloc] init];
storeConfig.sdkKey = @"这里填上的SDK Key";
storeConfig.sdkSecret = @"这里填上SDK secret";
storeConfig.apiServer = @"这里填上你们的服务器地址"; // 例如:https://api.finclip.com;
storeConfig.apiPrefix = @"/api/v1/mop";
FATConfig *config = [FATConfig configWithStoreConfigs:@[storeConfig]];
    
[[FATClient sharedClient] initWithConfig:config error:nil];

注意

  1. 从2.13.109版本开始,FinClip SDK 支持配置多个服务器信息,可以同时打开多个不同服务器上的小程序,所以我们提供了配置多个服务器信息的方式。
  2. configWithAppSecret:appKey:未来会弃用,请尽早替换为configWithStoreConfigs的方式构造FATConfig。
  3. 自2.34.1开始,不再需要配置apiPrefix。

以下是配置多个服务器初始化SDK的示例:

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中的配置项:

配置名称 配置描述
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等)
enableApmDataCompression apm数据上报时,是否压缩数据
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 胶囊里的深色分割线颜色

我们的默认胶囊是这样:

image.png

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

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

效果如下:

image.png

# 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;
}
/// 处理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.ft.miniProgram.callNativeAPI('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.ft.miniProgram.registNativeAPIHandler('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 全局唯一的录音管理器
© 2021 凡泰极客
  • 免费试用
  • 编组
  • 编组 2