startLivenessDetection接口的参数InteractiveLivenessConfig中可以设置successfulRouteUrl和failedRouteUrl分别作为人脸活体检测成功/失败后跳转的页面路径。页面路由只支持Router方式,不支持Navigation方式。
如何实现检测结束后自动跳转到Navigation路由的指定页面?
startLivenessDetection跳转到人脸活体检测页面的入口,使用Promise异步回调;startLivenessDetection跳转到人脸活体检测页面的入口,使用Promise异步回调获取跳转结果,使用callback回调获取检测结果。
实现思路:在startLivenessDetection接口的callback回调函数中获取检测结果,再根据检测结果调用NavPathStack.pushPath()(或NavPathStack.replacePath())方法跳转到成功/失败页面。
具体步骤:
/** * 人脸识别结果对象 */ export class DetectionResult { // 自定义code和message finalResult: Record<string, number | string>|undefined = undefined; }
interactiveLiveness.startLivenessDetection(routerOptions, (err: BusinessError, result: interactiveLiveness.InteractiveLivenessResult | undefined) => { // 当路由跳转错误时,获取结果失败,result返回undefined let detectionResult: DetectionResult = new DetectionResult(); if(err.code !== 0 && !result) { // 在发生错误如路由跳转失败/参数错误/权限被拒绝时,会抛出错误码,详见ArkTS API错误码 console.error(`LivenessCollectionIndex failed to detect. Code: ${err.code},message: ${err.message}`); detectionResult.finalResult = { 'code': err.code, 'message': 'Error' }; this.pathStack.pushPath({name: 'StartLivenessDetectionFailed', param: detectionResult}); return; } console.info(`LivenessCollectionIndex Succeeded in detecting result: ${result}`); if (result?.mPixelMap) { detectionResult.finalResult = { 'code': 0, 'message': 'Success' }; this.pathStack.pushPath({name: 'StartLivenessDetectionSuccess', param: detectionResult}); } else { detectionResult.finalResult = { 'code': -1, 'message': 'Failed' }; this.pathStack.pushPath({name: 'Detection', param: detectionResult}); } });
.onReady((context: NavDestinationContext) => { this.pathStack = context.pathStack; let detectionResult: DetectionResult = this.pathStack.getParamByIndex(1) as DetectionResult; if (detectionResult?.finalResult) { let message = detectionResult?.finalResult['message']; console.info(`Detection result is ${message}.`); } else { console.info(`Detection result is succeed.`); } });
完整示例如下:
{
"module": {
"name": "entry",
"type": "entry",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"deviceTypes": [
"phone"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"routerMap": "$profile:route_map", // 路由配置
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "$string:EntryAbility_desc",
"icon": "$media:layered_image",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"ohos.want.action.home"
]
}
]
}
],
"extensionAbilities": [
{
"name": "EntryBackupAbility",
"srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
"type": "backup",
"exported": false,
"metadata": [
{
"name": "ohos.extension.backup",
"resource": "$profile:backup_config"
}
],
}
],
"requestPermissions": [ // 权限声明
{
"name": "ohos.permission.CAMERA",
"reason": "$string:reason_of_camera",
"usedScene": {
"when": "always"
}
}
]
}
} {
"string": [
{
"name": "module_desc",
"value": "module description"
},
{
"name": "EntryAbility_desc",
"value": "description"
},
{
"name": "EntryAbility_label",
"value": "label"
},
{
"name": "reason_of_camera",
"value": "活体检测"
}
]
} {
"routerMap": [
{
"name": "Detection",
"pageSourceFile": "src/main/ets/pages/Detection.ets",
"buildFunction": "DetectionBuilder",
"data": {
"description" : "this is Detection"
}
},
{
"name": "StartLivenessDetectionSuccess",
"pageSourceFile": "src/main/ets/pages/StartLivenessDetectionSuccess.ets",
"buildFunction": "StartLivenessDetectionSuccessBuilder",
"data": {
"description" : "this is StartLivenessDetectionSuccessBuilder"
}
},
{
"name": "StartLivenessDetectionFailed",
"pageSourceFile": "src/main/ets/pages/StartLivenessDetectionFailed.ets",
"buildFunction": "StartLivenessDetectionFailedBuilder",
"data": {
"description" : "this is StartLivenessDetectionFailedBuilder"
}
}
]
} @Entry @Component struct Index { pageInfos: NavPathStack = new NavPathStack(); aboutToAppear(): void { let param = this.getUIContext().getRouter().getParams(); if (param) { this.pageInfos.pushPath({name: 'StartLivenessDetectionSuccess'}); } } build() { Navigation(this.pageInfos) { Column() { Button('去检测', { stateEffect: true, type: ButtonType.Capsule }) .width('80%') .height(40) .margin(20) .onClick(() => { this.pageInfos.pushPath({ name: 'Detection' }); //将name指定的NavDestination页面信息入栈 }) } } .mode(NavigationMode.Auto) .title('首页') } }
import { common, abilityAccessCtrl, Permissions } from '@kit.AbilityKit'; import { interactiveLiveness } from '@kit.VisionKit'; import { BusinessError } from '@kit.BasicServicesKit'; /** * 人脸识别结果对象 */ export class DetectionResult { // 自定义code和message finalResult: Record<string, number | string>|undefined = undefined; } @Builder export function DetectionBuilder() { Detection() } @Component export struct Detection { private context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext; @State pathStack: NavPathStack = new NavPathStack(); @State failResult: Record<string, number | string> = { 'code': 1008302000, 'message': '' }; private array: Array<Permissions> = ['ohos.permission.CAMERA']; private actionsNum: number = 3; private isSilentMode: interactiveLiveness.DetectionMode.INTERACTIVE_MODE = interactiveLiveness.DetectionMode.INTERACTIVE_MODE; build() { NavDestination() { Stack({ alignContent: Alignment.Top }) { Column() { Row() { Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) { Text('动作数量:' + this.actionsNum) .fontSize(30) .width('50%') } } } .margin({ left: 24, top: 80 }) .zIndex(1) Stack({ alignContent: Alignment.Bottom }) { Button('开始检测', { type: ButtonType.Normal, stateEffect: true }) .width(192) .height(40) .fontSize(16) .backgroundColor(0x317aff) .borderRadius(20) .margin({ bottom: 56 }) .onClick(() => { this.startDetection(); }) } .height('100%') } }.title('检测页面') .onReady((context: NavDestinationContext) => { this.pathStack = context.pathStack; if (context.pathInfo.param) { let detectionResult = context.pathInfo.param as DetectionResult; if (detectionResult.finalResult) { this.failResult = detectionResult.finalResult; } } }); } // 跳转到人脸活体检测控件 private routerLibrary() { let routerOptions: interactiveLiveness.InteractiveLivenessConfig = { isSilentMode: this.isSilentMode, routeMode: interactiveLiveness.RouteRedirectionMode.BACK_MODE, actionsNum: this.actionsNum }; if (canIUse('SystemCapability.AI.Component.LivenessDetect')) { interactiveLiveness.startLivenessDetection(routerOptions, (err: BusinessError, result: interactiveLiveness.InteractiveLivenessResult | undefined) => { // 当路由跳转错误时,获取结果失败,result返回undefined let detectionResult: DetectionResult = new DetectionResult(); if(err.code !== 0 && !result) { // 在发生错误如路由跳转失败/参数错误/权限被拒绝时,会抛出错误码,详见ArkTS API错误码 console.error(`LivenessCollectionIndex failed to detect. Code: ${err.code},message: ${err.message}`); detectionResult.finalResult = { 'code': err.code, 'message': 'Error' }; this.pathStack.pushPath({name: 'StartLivenessDetectionFailed', param: detectionResult}); return; } console.info(`LivenessCollectionIndex Succeeded in detecting result: ${result}`); if (result?.mPixelMap) { detectionResult.finalResult = { 'code': 0, 'message': 'Success' }; this.pathStack.pushPath({name: 'StartLivenessDetectionSuccess', param: detectionResult}); } else { detectionResult.finalResult = { 'code': -1, 'message': 'Failed' }; this.pathStack.pushPath({name: 'Detection', param: detectionResult}); } }); } else { console.error('LivenessCollectionIndex this api is not supported on this device'); } } // 校验CAMERA权限 private startDetection() { abilityAccessCtrl.createAtManager().requestPermissionsFromUser(this.context, this.array).then((res) => { for (let i = 0; i < res.permissions.length; i++) { if (res.permissions[i] === 'ohos.permission.CAMERA' && res.authResults[i] === 0) { this.routerLibrary(); } } }).catch((err: BusinessError) => { console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`); }); } }
import { DetectionResult } from './Detection'; @Builder export function StartLivenessDetectionSuccessBuilder() { StartLivenessDetectionSuccess() } @Component export struct StartLivenessDetectionSuccess { @State pathStack: NavPathStack = new NavPathStack(); build() { NavDestination() { Stack({ alignContent: Alignment.Top }) { Column() { Stack({ alignContent: Alignment.Bottom }) { Text('Success') .fontSize(100) .fontColor(Color.Green) .align(Alignment.Center) .margin({ bottom: 260 }) } } } } .onReady((context: NavDestinationContext) => { this.pathStack = context.pathStack; let detectionResult: DetectionResult = this.pathStack.getParamByIndex(1) as DetectionResult; if (detectionResult?.finalResult) { let message = detectionResult?.finalResult['message']; console.info(`Detection result is ${message}.`); } else { console.info(`Detection result is succeed.`); } }); } }
import { DetectionResult } from './Detection'; @Builder export function StartLivenessDetectionFailedBuilder() { StartLivenessDetectionFailed() } @Component export struct StartLivenessDetectionFailed { @State pathStack: NavPathStack = new NavPathStack(); build() { NavDestination() { Stack({ alignContent: Alignment.Top }) { Column() { Stack({ alignContent: Alignment.Bottom }) { Text('Failed') .fontSize(100) .fontColor(Color.Red) .fontWeight(FontWeight.Bolder) .align(Alignment.Center) .margin({ bottom: 260 }) } } } } .onReady((context: NavDestinationContext) => { this.pathStack = context.pathStack; let detectionResult: DetectionResult = this.pathStack.getParamByIndex(1) as DetectionResult; if (detectionResult?.finalResult) { let message = detectionResult?.finalResult['message']; console.info(`Detection result is ${message}.`); } else { console.info(`Detection result is failed.`); } }); } }