APP内嵌H5兼容性配置
APP内嵌H5兼容性配置
如您需要在自研APP中以webview的方式嵌入H5页面,请参照下文进行 iOS 及 Android 手机的兼容性适配。我们对一些需要做的配置进行了处理和封装,以framework(iOS)和Js-Bridge SDK(安卓)的形式提供,提升您的接入效率。
为了更好地配合组件使用,请在您的认证URL后,增加参数&useNative=1,以使用js-bridge通信功能。如: https://brain.baidu.com/face/print/?token=xxx&successUrl=https://xxx&failedUrl=https://xxx%3CBr%3E&useNative=1
iOS
请您按如下步骤完成SDK集成,接着参照H5方案接入指南完成方案配置和token获取,生成认证H5 URL,使用生成的H5 URL替换示例代码中urlString。
1、配置依赖
- 将BDAIFaceH5.framework添加到工程中,同时配置依赖库为Embed & Sign

2、配置权限
- 在Info.plist添加权限配置,否则app运行会崩溃。
| 名称 | 是否必选 | 说明 |
|---|---|---|
| Privacy - Camera Usage Description | 是 | 相机权限 |
| Privacy - Microphone Usage Description | 是 | 麦克风权限 |
3、使用方法
- SDK结构
向集成方提供BDH5Browser类,BDH5Browser继承自UIViewController,对WKWebView进行了封装和适配,并提供了更为简洁的调用方法。
- 参数释义
| 方法名 | 返回值 | 说明 | 备注 |
|---|---|---|---|
| homeUrl | 无 | 加载H5方案主页地址 | 必要参数 |
| isShowCloseButton | 无 | 是否展示关闭按钮,默认不展示 | 非必要参数 |
| js2NativeTags | 无 | 与JS交互的约定key值,用于捕捉JS to Native的事件,通过BDH5BrowserDelegate回调自定义所需功能实现 | 非必要参数 |
| bdH5BrowserDelegate | 无 | BDH5BrowserDelegate 代理 | 非必要参数 |
- 接口方法 通过navigationController推出browser。
1(void)showH5BrowserWithNavigationController:(UINavigationController *)navigationController animated:(BOOL)isAnimated;
通过viewController以present的形式推出browser。
1- (void)showH5BrowserWithPresentViewController:(UIViewController *)viewController isFullScreen:(BOOL)isFull animated:(BOOL)isAnimated completion:(void (^ __nullable)(void))completion;
销毁视图,completion只有在present模式下生效。
1- (void)dismissH5BrowserAnimated:(BOOL)isAnimated completion:(void (^ __nullable)(void))completion;
BDH5BrowserDelegate,用于客户自定义实现JS to Native事件回调,可根据自身业务选择实现。
1@protocol BDH5BrowserDelegate <NSObject>
2
3@optional
4- (void)bdH5BrowserUserContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;
5
6@end
- 示例代码
在需要调用H5人脸的地方调用该示例代码即可
1 // 百度人脸URL
2 NSString *urlString = @"https://ai-face-h5-evaluation.weiyun.baidu.com/face/print/h5demo";
3
4 if (self.urlTF.text.length > 0) {
5 urlString = self.urlTF.text;
6 }
7
8 _desController = [[BDH5Browser alloc] init];
9
10 // 设置URL,必传。否则页面无法加载
11 _desController.homeUrl = urlString;
12
13 // 设置与JS协商的key值,以实现 JS to Native 的事件回调。此处js2Native是与百度人脸JS端协商好的key值,用于JS与Native通信,切勿随意更改
14 _desController.js2NativeTags = @[@"js2Native"];
15
16 // webBrowser messageHandler 事件回调代理
17 _desController.bdH5BrowserDelegate = self;
18
19 // 是否展示关闭按钮,默认不展示
20 _desController.isShowCloseButton = YES;
21
22 // push or present
23// [_desController showH5BrowserWithNavigationController:self.navigationController animated:YES];
24
25// // push or present
26 [_desController showH5BrowserWithPresentViewController:self isFullScreen:YES animated:YES completion:nil];
27
BDH5BrowserDelegate代理实现实例。
1- (void)bdH5BrowserUserContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
2 NSString *messageName = message.name;
3 NSString *messageBody = message.body;
4
5 NSLog(@"****************:%@", message.name); // 方法名
6 NSLog(@"****************:%@", message.body); // 传递的数据
7
8 // 可根据协商key值进行自定义native逻辑,以下仅做示例展示
9 if ([messageName isEqualToString:@"js2Native"]) {
10
11 dispatch_async(dispatch_get_main_queue(), ^{
12 [self->_desController dismissH5BrowserAnimated:YES completion:nil];
13 self->_desController = nil;
14
15 UIAlertController *alert = [UIAlertController alertControllerWithTitle:messageName message:messageBody preferredStyle:UIAlertControllerStyleAlert];
16 UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleDestructive handler:nil];
17 [alert addAction:okAction];
18 [self presentViewController:alert animated:YES completion:nil];
19 });
20
21 }
22
23}
4、SDK及示例demo源码
- 链接: https://pan.baidu.com/s/1DsQoj94eGRLTZlEDSH258g
- 提取码: 请联系您的商务经理获取
安卓
请您先参考本文档完成下述步骤,接着参照H5方案接入指南完成方案配置和token获取,生成认证H5 URL,并将H5 URL填写在jsWebview的loadUrl方法。
1、配置依赖
- 下载jsbridge.aar,放入工程libs目录。 链接: https://pan.baidu.com/s/1w5rMLGGdXvINDeyg2Zz7FA 提取码: 请联系您的商务经理获取
- 如果您使用androidx软件包,请下载以下版本,放入工程libs目录。 链接: https://pan.baidu.com/s/1po-gQdJvjAj47xeXt3opKw 提取码: 请联系您的商务经理获取
- 在app目录下的build.gradle文件中,配置jsbridge.aar依赖。
12、repositories {
2 flatDir {
3 dirs 'libs'
4 }
5}
6dependencies {
7 // jsBridge-SDK.aar
8 compile(name: 'lib-jsbridge-1.0-release', ext: 'aar')
9}
2、权限
| 名称 | 是否必选 | 说明 |
|---|---|---|
| android.permission.INTERNET | 是 | 网络权限 |
| android.permission.CAMERA | 是 | 拍照权限 |
| android.permission.RECORD_AUDIO | 是 | 录音权限 |
3、使用方法
- JsWebview作为承载动态页面的容器,在JsBridge-SDK中用于加载web页面、相机&麦克风等相关权限申请功能、调起系统相机拍照&录像功能、返回键事件处理功能。
| 方法名 | 返回值 | 说明 | 备注 |
|---|---|---|---|
| loadUrl() | 无 | 加载h5方案主页地址 | webview自带方法 |
| checkPermisions() | boolean | 相机&录音权限能力封装:判断应用是否开启相机权限和录音权限,通过返回值判断是否已开启相关权限。有权限则返回true,调用loadUrl(),来加载h5主页地址。没有权限则返回false,方法内部会调用系统方法来申请权限。Manifest.permission.CAMERA 相机权限 Manifest.permission.RECORD_AUDIO 录音权限 | 需要调用 |
| setJs2NativeListener() | 无 | 设置Js2Native的监听器,H5人脸实名认证会将核验完成事件进行回调,可以根据回调事件来做后续的逻辑处理。 | |
| onKeyDown() | boolean | 对返回键事件进行处理,用于H5页面回退场景,避免Activity销毁。需要重写Activity的onKeyDown回调方法,并在onKeyDown方法内部调用此方法。返回值:true,处理返回值:false,不处理 | 需要调用 |
| onPermisonResult() | boolean | 相机权限申请回调:对申请权限的回调进行处理,重写系统的onRequestPermisionResult回调方法,并在onRequestPermisionResult方法内部调用此方法。通过返回值判断用户是否开启相关权限,用户开启权限则返回true,则调用loadUrl(),来加载h5主页地址。用户未开启权限则返回false,提示申请权限失败。 | 需要调用 |
| onCaptureResult() | 无 | 系统相机拍照&相机录像能力回调:相机拍照&相机录像回调进行处理,重写系统的onActivityResult回调方法,并在onActivityResult方法内部调用此方法。无返回值。 | 需要调用 |
4、示例代码
- 在布局文件中,增加jswebview组件
1 <RelativeLayout
2 android:id="@+id/js_layout"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent">
5 <com.baidu.ai.face.widget.JsWebView
6 android:id="@+id/js_webview"
7 android:layout_width="match_parent"
8 android:layout_height="match_parent" />
9 </RelativeLayout>
- 在Activity中,导入com.baidu.ai.face.widget.JsWebView
1 import com.baidu.ai.face.widget.JsWebView
- 在Actvity中,找到jswebview组件,通过checkPermission方法来判断是否拥有相关权限,有权限则直接加载h5地址,无权限方法内部会申请相关权限。
1 jsWebview = (JsWebView) findViewById(R.id.js_webview);
2 if (jsWebview.checkPermissions()) {
3 // 加载H5页面
4 jsWebview.loadUrl(mUrl);
5 }
- 在JsWebView上增加Js2NativeListener,H5人脸实名认证会将核验完成事件进行回调,可以根据回调事件来做相应的逻辑处理。
1// 通过JsBridge监听消息
2jsWebView.setJs2NativeListener(new Js2NativeListener() {
3 @Override
4 public void js2Native(int code, String message) {
5 Toast.makeText(jsWebView.getContext(),
6 "js->Native:" + "code:" + code + ",value:" + message, Toast.LENGTH_LONG).show();
7 }
8});
- 在Activity的onRequestPermisionResult调用jswebview的onPermissionsResult方法,对权限回调进行处理,返回值为true,权限申请成功,直接加载h5地址。返回值为false,权限申请失败,申请失败需要增加自己的业务处理逻辑。
1 @Override
2 public void onRequestPermissionsResult(int requestCode, String[] permissions,
3 int[] grantResults) {
4 if (jsWebview.onPermissionsResult(requestCode, permissions, grantResults)) {
5 // 加载H5页面
6 jsWebview.loadUrl(mUrl);
7 } else {
8 // 权限申请失败,增加失败处理逻辑
9 }
10 }
- 在Activity的onKeyDown中调用jswebview的onKeyDown方法,内部封装了返回事件的处理。
1 @Override
2 public boolean onKeyDown(int keyCode, KeyEvent event) {
3 return jsWebview.onKeyDown(JsActivity.this, keyCode, event);
4 }
- 在Activity的onActivityResult中调用jswebview的onCaptureResult方法,内部封装了通过相机拍照,通过相机录像的回调处理逻辑。
1 @Override
2 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
3 super.onActivityResult(requestCode, resultCode, data);
4 jsWebview.onCaptureResult(requestCode, resultCode, data);
5 }
鸿蒙
请您先参考本文档完成下述步骤,接着参照H5方案接入指南完成方案配置和token获取,生成认证H5 URL,使用生成的H5 URL替换示例代码中URL字符串。
1、添加依赖
下载jsbridge.har,放入工程libs目录。 链接: https://pan.baidu.com/s/1w5rMLGGdXvINDeyg2Zz7FA 提取码: 请联系您的商务经理获取
在项目的 oh-package.json5 中添加:
1{
2 "dependencies": {
3 "@aspect/jsbridge": "file:./libs/jsbridge.har"
4 }
5}
添加到项目
1# 将 HAR 文件复制到项目 libs 目录
2cp jsbridge.har your_project/libs/
配置依赖
1// oh-package.json5
2{
3 "dependencies": {
4 "@aspect/jsbridge": "file:./libs/jsbridge.har"
5 }
6}
2、权限
| 名称 | 是否必选 | 说明 |
|---|---|---|
| ohos.permission.INTERNET | 是 | 网络权限 |
| ohos.permission.CAMERA | 是 | 拍照权限 |
| ohos.permission.MICROPHONE | 是 | 录音权限 |
3、API 参考
JsBridgeManager
JSBridge 的核心管理类,负责桥接 WebView 与 JavaScript 的通信。
构造函数
1constructor(
2 controller: webview.WebviewController, // WebView 控制器
3 bridgeName?: string, // JS 访问的对象名,默认 'jsBridge'
4 handler?: JsBridgeHandler // 自定义 Handler
5)
方法列表
| 方法 | 参数 | 返回值 | 说明 |
|---|---|---|---|
setCallback(callback) |
JsBridgeCallback |
void |
设置 JS 调用回调监听 |
register(methods?) |
string[] |
boolean |
注册 JSBridge,返回是否成功 |
refreshIfNeeded() |
- | boolean |
刷新 WebView 使 Bridge 生效 |
getHandler() |
- | JsBridgeHandler |
获取 Handler 实例 |
WebViewHelper
WebView 辅助工具类,提供常用的 WebView 配置和功能。
1import { WebViewHelper } from '@aspect/jsbridge';
方法列表
| 方法 | 参数 | 返回值 | 说明 |
|---|---|---|---|
handleBackPress(controller) |
WebviewController |
boolean |
处理 WebView 返回键逻辑 |
canGoBack(controller) |
WebviewController |
boolean |
检查是否可以后退 |
canGoForward(controller) |
WebviewController |
boolean |
检查是否可以前进 |
goForward(controller) |
WebviewController |
boolean |
前进到下一页 |
refresh(controller) |
WebviewController |
void |
刷新当前页面 |
stop(controller) |
WebviewController |
void |
停止加载 |
clearHistory(controller) |
WebviewController |
void |
清除历史记录 |
handlePermissionRequest(event) |
PermissionRequestEvent |
void |
自动授予 WebView 权限请求 |
denyPermissionRequest(event) |
PermissionRequestEvent |
void |
拒绝 WebView 权限请求 |
grantPermission(permissions?) |
Array<Permissions> |
Promise<boolean> |
申请系统权限 |
JsBridgeCallback
JS 调用原生方法时的回调接口。
1interface JsBridgeCallback {
2 /**
3 * JS 调用原生方法时触发
4 * @param code 状态码
5 * @param message 消息内容
6 */
7 onJsCall(code: string, message: string): void;
8}
JsBridgeHandler
提供给 JS 调用的原生方法集合,可被继承以扩展更多方法。
| 方法 | 参数 | 说明 |
|---|---|---|
setCallback(callback) |
JsBridgeCallback |
设置回调 |
js2Native(code, message) |
string, string |
默认的 JS 调用方法 |
4、使用示例
基础通信
原生端 (ArkTS)
1import { webview } from '@kit.ArkWeb';
2import { JsBridgeManager, JsBridgeCallback } from '@aspect/jsbridge';
3
4@Entry
5@Component
6struct BasicExample {
7 controller: webview.WebviewController = new webview.WebviewController();
8 private jsBridgeManager?: JsBridgeManager;
9
10 build() {
11 Column() {
12 Web({ src: $rawfile("index.html"), controller: this.controller })
13 .javaScriptAccess(true)
14 .domStorageAccess(true)
15 // 在 onControllerAttached 中注册
16 .onControllerAttached(() => {
17 this.jsBridgeManager = new JsBridgeManager(this.controller);
18 this.jsBridgeManager.setCallback({
19 onJsCall: (code: string, message: string) => {
20 console.info(`JS调用: code=${code}, message=${message}`);
21 }
22 });
23 this.jsBridgeManager.register();
24 })
25 // 在 onPageEnd 中刷新(仅首次)
26 .onPageEnd(() => {
27 this.jsBridgeManager?.refreshIfNeeded();
28 })
29 }
30 }
31}
Web 端 (HTML)
1<button id="callNative">调用原生方法</button>
2<script>
3 document.getElementById('callNative').onclick = () => {
4 window.jsBridge?.js2Native('SUCCESS', JSON.stringify({ action: 'showToast' }));
5 };
6</script>
处理权限请求
1import { webview } from '@kit.ArkWeb';
2import { WebViewHelper } from '@aspect/jsbridge';
3
4@Entry
5@Component
6struct WebPageWithPermission {
7 controller: webview.WebviewController = new webview.WebviewController();
8
9 async onPageShow(): Promise<void> {
10 await WebViewHelper.grantPermission(); // 申请相机、麦克风权限
11 }
12
13 build() {
14 Column() {
15 Web({ src: "https://example.com", controller: this.controller })
16 .javaScriptAccess(true)
17 .onPermissionRequest((event) => {
18 WebViewHelper.handlePermissionRequest(event);
19 })
20 }
21 }
22}
处理返回键
1import { webview } from '@kit.ArkWeb';
2import { WebViewHelper } from '@aspect/jsbridge';
3
4@Entry
5@Component
6struct WebPageWithBack {
7 controller: webview.WebviewController = new webview.WebviewController();
8
9 onBackPress(): boolean | void {
10 return WebViewHelper.handleBackPress(this.controller);
11 }
12
13 build() {
14 Column() {
15 Web({ src: $rawfile("index.html"), controller: this.controller })
16 .javaScriptAccess(true)
17 }
18 }
19}
