本文介绍如何将 H5 容器和离线包组件接入到 iOS 客户端。H5 容器和离线包支持 基于 mPaaS 框架接入、基于已有工程且使用 mPaaS 插件接入 和 基于已有工程且使用 CocoaPods 接入 三种接入方式。通过使用 H5 容器和离线包可以实现初始化容器、唤起容器、实现 H5 与 Native 的双向通信、加载和使用离线包、集成 Nebula 容器自动化埋点能力及查看埋点数据等功能。
前置条件
您已经接入工程到 mPaaS。更多信息,请参见以下内容:
添加 SDK
根据您采用的接入方式,请选择相应的添加方式。
使用 mPaaS Xcode Extension。此方式适用于采用了 基于 mPaaS 框架接入 或 基于已有工程且使用 mPaaS 插件接入 的接入方式。
点击 Xcode 菜单项 Editor > mPaaS > 编辑工程,打开编辑工程页面。
选择 H5 容器&离线包,保存后点击 开始编辑,即可完成添加。
使用 cocoapods-mPaaS 插件。此方式适用于采用了 基于已有工程且使用 CocoaPods 接入 的接入方式。
在 Podfile 文件中,使用
mPaaS_pod "mPaaS_Nebula"
添加 H5 容器组件依赖。执行
pod install
即可完成接入。
使用 SDK
本文将结合 H5 容器和离线包 官方 Demo 介绍如何在 10.1.60 及以上版本的基线中使用 H5 容器 SDK。
H5 容器 SDK 的整个使用过程主要分为以下 5 步:
1 初始化配置
1.1 初始化容器
为了使用 Nebula 容器,您需要在程序启动完成后调用 SDK 接口,对容器进行初始化。初始化必须在
DTFrameworkInterface
的- (void)application:(UIApplication *)application beforeDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions
中进行。在 mPaaS 框架提供的分类DTFrameworkInterface +(项目工程名)
中重写此方法。- (void)application:(UIApplication *)application beforeDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 初始化容器 [MPNebulaAdapterInterface initNebula]; }
若您需要使用 预置离线包、自定义 JSAPI 和 Plugin 等功能,请将上方代码中的
initNebula
接口替换为下方代码中的initNebulaWith
接口,传入对应参数对容器进行初始化。presetApplistPath:自定义的预置离线包的包信息路径。
appPackagePath:自定义的预置离线包的包路径。
pluginsJsapisPath:自定义 JSAPI 和 Plugin 文件的存储路径。
- (void)application:(UIApplication *)application beforeDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 初始化容器 NSString *presetApplistPath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"MPCustomPresetApps.bundle/h5_json.json"] ofType:nil]; NSString *appPackagePath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"MPCustomPresetApps.bundle"] ofType:nil]; NSString *pluginsJsapisPath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"Poseidon-UserDefine-Extra-Config.plist"] ofType:nil]; [MPNebulaAdapterInterface initNebulaWithCustomPresetApplistPath:presetApplistPath customPresetAppPackagePath:appPackagePath customPluginsJsapisPath:pluginsJsapisPath]; }
说明initNebula
和initNebulaWithCustomPresetApplistPath
是两个并列的方法,不支持同时调用。
配置小程序包请求时间间隔,mPaaS 支持配置小程序包的请求时间间隔,可全局配置或单个配置。
全局配置:您可以在初始化容器时通过如下代码设置离线包或⼩程序的更新频率。
[MPNebulaAdapterInterface shareInstance].nebulaUpdateReqRate = 7200;
其中 7200 是设置全局更新间隔的值,7200 为默认值,代表间隔时长,单位为秒,您可修改此值来设置您的全局离线包请求间隔,范围为 0 ~ 86400 秒(即 0 ~ 24 小时,0 代表无请求间隔限制)。
单个配置:即只对当前小程序包配置。可在控制台中前往 单个配置 > 添加离线包 > 扩展信息 中填入
{"asyncReqRate":"1800"}
来设置请求时间间隔。详情参见 创建 H5 离线包 中的 扩展信息。
1.2 定制容器
如有需要,您可以通过设置
MPNebulaAdapterInterface
的属性值来定制容器配置。必须在DTFrameworkInterface
的- (void)application:(UIApplication *)application afterDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions
中设置,否则会被容器默认配置覆盖。- (void)application:(UIApplication *)application afterDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 定制容器 [MPNebulaAdapterInterface shareInstance].nebulaVeiwControllerClass = [MPH5WebViewController class]; [MPNebulaAdapterInterface shareInstance].nebulaNeedVerify = NO; [MPNebulaAdapterInterface shareInstance].nebulaUserAgent = @"mPaaS/Portal"; [MPNebulaAdapterInterface shareInstance].nebulaCommonResourceAppList = @[@"77777777"]; }
属性含义如下:
属性
含义
备注
nebulaVeiwControllerClass
H5 页面的基类
默认为 H5WebViewController。若需指定所有 H5 页面的基类,可直接设置此接口。
重要基类必须继承自 H5WebViewController。
nebulaWebViewClass
设置 WebView 的基类
> 10.1.60:默认为 H5WKWebView。自定义的 WebView 必须继承 H5WKWebView。
= 10.1.60:不支持自定义。
nebulaUseWKArbitrary
设置是否使用 WKWebView 加载离线包页面
> 10.1.60:默认为 YES。
= 10.1.60:默认为 NO。
nebulaUserAgent
设置应用的 UserAgent
设置的 UserAgent 会作为后缀添加到容器默认的 UA 上。
nebulaNeedVerify
是否验签,默认为 YES
若 配置离线包 时未上传私钥文件,此值需设为 NO,否则离线包加载失败。
nebulaPublicKeyPath
离线包验签的公钥路径
与 配置离线包 时上传的私钥对应的公钥路径。
nebulaCommonResourceAppList
公共资源包的 appId 列表
-
errorHtmlPath
当 H5 页面加载失败时展示的 HTML 错误页路径
默认读取
MPNebulaAdapter.bundle/error.html
。configDelegate
设置自定义开关 delegate
提供全局修改容器默认开关值的能力。
1.3 更新离线包
启动完成后,全量请求所有离线包信息,检查服务端是否有更新包。为了不影响应用启动速度,建议在
(void)application:(UIApplication \*)application afterDidFinishLaunchingWithOptions:(NSDictionary \*)launchOptions
之后调用。
- (void)application:(UIApplication *)application afterDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// 定制容器
[MPNebulaAdapterInterface shareInstance].nebulaVeiwControllerClass = [MPH5WebViewController class];
[MPNebulaAdapterInterface shareInstance].nebulaNeedVerify = NO;
[MPNebulaAdapterInterface shareInstance].nebulaUserAgent = @"mPaaS/Portal";
[MPNebulaAdapterInterface shareInstance].nebulaCommonResourceAppList = @[@"77777777"];
// 全量更新离线包
[[MPNebulaAdapterInterface shareInstance] requestAllNebulaApps:^(NSDictionary *data, NSError *error) {
NSLog(@"");
}];
}
初始化完成后,效果如下:
1.4 非框架托管配置
非框架托管是指 App 的生命周期并没有交给 mPaaS 框架托管,而是指定为自定义的 delegate。如果采用了非框架托管的方式(如下图所示),则需进行额外配置,请参照本文提供的方法初始化 mPaaS 框架。如果采用了 mPaaS 框架托管 App 的生命周期,则无需进行额外配置。
如果您的基线版本 <10.1.68.25,建议您升级、选用新版本基线。
只需在应用的 window 及 navigationController 创建完成后,调用以下方法即可,不再需要创建 bootloader、隐藏框架 window 等操作。
支持不继承 DFNavigationController。
若 App 有多个导航栏,且需要在不同导航栏中打开不同离线包,在切换导航栏后需重新设置容器的导航栏。
1.5 非框架托管配置(10.1.68.25 以下版本)
非框架托管是指 App 的生命周期并没有交给 mPaaS 框架托管,而是指定为自定义的 delegate。如果采用了非框架托管 App 生命周期的方式(如下图所示),需进行额外配置,请参照本文提供的方法初始化 mPaaS 框架。如果采用了 mPaaS 框架托管 App 的生命周期,则无需进行额外配置。
如果您的基线版本 ≥10.1.68.25,请参考 1.4 非框架托管配置 进行配置。对于 10.1.68.25 及以上版本的基线,1.4 非框架托管配置 提供了快速、简洁的初始化框架方法,如果您使用的基线版本仍低于 10.1.68.25,建议您升级、选用 10.1.68.25 或以上版本基线。
1.5.1 启动 mPaaS 框架
在当前应用的 didFinishLaunchingWithOptions
方法中调用 [[DTFrameworkInterface sharedInstance] manualInitMpaasFrameworkWithApplication:application launchOptions:launchOptions];
来启动 mPaaS 框架。
启动框架必须在当前应用 window 和 navigation 初始化完成后调用,否则无法生效。
1.5.2 创建应用启动器
创建继承 DTBootLoader 的子类,重写 createWindow
和 createNavigationController
方法,返回当前应用自己的 window 和 navigationControlle。
设置 window:当前应用的 keyWindow。
设置 navigationController:当前应用 keyWindow 的 rootviewcontroller,必须继承 DFNavigationController。
1.5.3 指定应用启动器
在 DTFrameworkInterface 的 category 中重写方法,指定当前应用自己的 bootloader,并隐藏 mPaaS 框架默认的 window 和 launcher 应用。
2 唤起容器
容器初始化完成后,就可以唤起一个 H5 容器。分为以下三种情况。
基于在线 URL 或本地 HTML 文件,创建一个 H5 容器。 示例代码如下:
// 打开在线 URL [[MPNebulaAdapterInterface shareInstance] startH5ViewControllerWithParams:@{@"url": @"https://tech.antfin.com/products/MPAAS"}]; // 打开本地 HTML 页面 NSString *path = [[NSBundle mainBundle].bundlePath stringByAppendingFormat:@"/%@/%@", @"MPH5Demo.bundle", @"H52Native.html"]; if ([path length] > 0) { [[MPNebulaAdapterInterface shareInstance] startH5ViewControllerWithParams:@{@"url": path}]; }
基于传入的离线包信息,创建一个 H5 容器,并自动 push 打开。示例代码如下:
[[MPNebulaAdapterInterface shareInstance] startH5ViewControllerWithNebulaApp:@{@"appId":@"90000000"}];
基于传入的离线包信息,创建一个 H5 容器,并返回创建的 H5 容器实例(一般用在首页 tab 页面)。 示例代码如下:
[[MPNebulaAdapterInterface shareInstance] createH5ViewControllerWithNebulaApp:@{@"appId":@"90000000"}];
3 实现 H5 与 Native 双向通信
您可以通过调用 JSAPI 和监听特定事件来实现 H5 与 Native 双向通信。
3.1 在 H5 页面调用 Native 功能
您可以通过调用 JSAPI 来实现 H5 到 Native 的通信。
Nebula 容器支持的 JSAPI 及相关参数说明,请参见 内置 JSAPI。
示例
调用 JSAPI 接口 pushWindow
,实现“在 H5 页面点击某个按钮时,加载一个新页面”的需求:
AlipayJSBridge.call('pushWindow', {
url: 'https://tech.antfin.com',
param: {
readTitle: true,
defaultTitle: true,
// ...
}
}, function(data) {alert('调用结果'+JSON.stringify(data)); });
AlipayJSBridge 说明
AlipayJSBridge 是 Nebula 容器自动注入的 JSBridge。在 Window.onload
以后,容器会生成一个全局变量 AlipayJSBridge,然后触发 AlipayJSBridgeReady 事件。AlipayJSBridge 注入是一个异步过程,因此需要先监听 AlipayJSBridgeReady 事件再调用接口。
示例代码如下:
<h1>bridge 使用方法</h1>
<script>
function ready(callback) {
if (window.AlipayJSBridge) {
callback && callback();
} else {
document.addEventListener('AlipayJSBridgeReady', callback, false);
}
}
ready(function(){
alert('bridge ready');
});
</script>
3.2 在 Native 页面调用 H5 功能
您可以通过监听特定事件来实现 Native 到 H5 的通信。Nebula 容器支持的事件,参见 事件扩展列表。
document.addEventListener('back', function (e) {
if(confirm('back已拦截,是否确定返回?')) {
// do something;
}
}, false);
除了 Nebula 容器默认支持的事件外,您还可以在 Native 端通过以下方式自定义事件让前端来监听。
// self: 当前 H5 页面所在的 VC
// data:native 传递给前端的参数
// callBack:前端收到事件后的回调
[self callHandler:@"customEvent" data:@{@"key":@"value"} responseCallback:^(id responseData) {
NSLog(@"前端收到事件后的回调: %@", responseData);
}];
3.3 扩展 Nebula 容器能力
如果 Nebula 容器提供的基础 H5 页面双向通信能力无法满足需求,您可以对 Nebula 进行扩展开发:
JSAPI:如果您要从 H5 页面发起 Native 功能调用(如显示一个 ActionSheet,或显示联系人对话框),那么您需要扩展 JSAPI。JSAPI 可以通过 handler 方法,让您很方便地增加 H5 页面的 Native 功能调用来实现特定功能。具体的自定义方法,请参见 自定义 JSAPI。
Plugin:如果您需要在某个时机(如进入页面、收到请求等)做某些事情(如记录埋点、修改返回数据等),那么您需要开发一个插件 (Plugin)。在插件中订阅相应的事件后,就可以在 handler 中对事件所携带的数据进行加工处理。具体的自定义方法,请参见 自定义插件。
4 加载离线包
传统的在线 H5 技术容易受到网络环境影响,从而影响 H5 页面的性能。为了最大程度摆脱网络对 H5 页面加载的影响,您可以将不同的业务封装打包成为一个离线包,通过发布平台下发到客户端,对客户端资源进行更新。更多信息,请参见 离线包简介 和 使用离线包。
5 H5 容器埋点
在 H5 页面加载时,Nebula 容器会自动监控加载性能,并捕获相关的行为数据和异常报错数据。更多信息,请参见 H5 容器埋点。