鸿蒙实现自定义类似活体检测功能

一.背景

目前需要实现活体检测功能,而且是需要静默活体,但是现在官方的活体API还不支持静默,第三方的SDK也不支持,现在自定义一个类似活体检测的功能,但是不会去检测是否活体,拿到照片以后去调用人脸识别

二.实现思路

先调用相机,将相机设置为前置摄像头,将当前相机内容使用XComponent实时渲染,启用定时拍照功能,设置定时器,时间到以后利用截图组件功能去做,然后拿到图片地址去进行人脸识别,不保存到本地

三.代码

这边只放了首页代码,其余代码会在包里,在文章后附带

使用的时候将包放到项目中,直接跳转或者引用xsComponent这个页面

TypeScript 复制代码
/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

import { CameraConstants } from './constants/CameraConstants';
import { CameraUtils } from './utils/CameraUtils';
import { abilityAccessCtrl, bundleManager, common, PermissionRequestResult, Permissions } from '@kit.AbilityKit';
import { BusinessError, emitter } from '@kit.BasicServicesKit';
import Logger from './utils/Logger';
import { TwiceReqPermissionButtonComponent } from './component/TwiceReqPermissionButtonComponent';
import { StackXComponent } from './component/StackXComponent';
import LoadingDialog from '@lyb/loading-dialog';
import { DynamicsRouter } from 'common';

@Builder
export function xsIndexBuilder() {
  xsIndex()
}

@Entry
@Component
struct xsIndex {
  @Provide cameraPosition: number = 1; // 固定为前置摄像头
  @Provide notHasPermission: boolean = true;
  @Provide surfaceId: string = '';
  @Provide timerShooting: number = 3; // 固定3秒
  @Provide captureTimer: number = 0;
  @Provide isVisibleTimerSet: boolean = false;
  @Provide isVisibleTimer: boolean = false;
  @Provide isVisibleCapture: boolean = true;
  @Provide captureClickFlag: number = 0;
  @State autoCaptureStarted: boolean = false; // 标记是否已开始自动拍照
  private uiContext: UIContext = this.getUIContext();
  private cameraUtils = new CameraUtils(this.uiContext);

  checkPermissions(permission: Permissions) {
    let atManager = abilityAccessCtrl.createAtManager();
    let bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);
    let tokenID = bundleInfo.appInfo.accessTokenId;
    let authResults = atManager.checkAccessTokenSync(tokenID, permission);
    return authResults === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
  }

  aboutToDisappear(): void {
    this.cameraUtils.releaseCamera();
  }

 

    AppStorage.setOrCreate('cameraUtils', this.cameraUtils);
    let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
    let context: Context = this.getUIContext().getHostContext() as common.UIAbilityContext;
    atManager.requestPermissionsFromUser(context, ['ohos.permission.CAMERA'])
      .then((data: PermissionRequestResult) => {
        if (data.authResults[0] === 0) {
          this.notHasPermission = false;
          this.cameraUtils.cameraShooting(this.cameraPosition, this.surfaceId, context);
          // 延迟启动自动拍照,等待相机初始化完成
          setTimeout(() => {
            this.startAutoCapture();
          }, 500);
        } else if (data.authResults[0] === -1) {
          this.notHasPermission = true;
        }
      })
      .catch((err: BusinessError) => {
        Logger.error(`data: ${JSON.stringify(err)}`);
      });
  }

  // 开始自动拍照流程
  startAutoCapture(): void {
    if (this.autoCaptureStarted || this.notHasPermission) {
      return;
    }
    this.autoCaptureStarted = true;
    this.isVisibleTimer = true;
    this.captureTimer = this.timerShooting;
    this.isVisibleCapture = false;

    // 3秒后自动拍照
    setTimeout(() => {
      this.cameraUtils.capture(true); // 前置摄像头需要镜像
      this.captureClickFlag = this.captureClickFlag + 1;
      this.isVisibleCapture = true;
      this.isVisibleTimer = false;
    }, this.captureTimer * 1000);
  }

  onPageShow() {
    if (!this.notHasPermission) {
      let permissions: Permissions = 'ohos.permission.CAMERA';
      if (this.checkPermissions(permissions)) {
        this.cameraUtils.cameraShooting(this.cameraPosition, this.surfaceId, this.getUIContext().getHostContext()!);
        this.notHasPermission = false;
        // 如果还没有开始自动拍照,则启动
        if (!this.autoCaptureStarted) {
          setTimeout(() => {
            this.startAutoCapture();
          }, 500);
        }
      } else {
        this.notHasPermission = true;
      }
    }
  }

  onPageHide(): void {
    if (!this.notHasPermission) {
      this.cameraUtils.releaseCamera();
    }
  }

  build() {
    NavDestination() {
      Column() {
        if (this.notHasPermission) {
          TwiceReqPermissionButtonComponent();
        } else {
          Row() {
            Image($r('app.media.back'))
              .width(25)
              .height(25)
              .onClick(() => {
                DynamicsRouter.pop()
              })
          }.width('100%').padding(15)

          StackXComponent();
        }
      }
      .height(CameraConstants.FULL_SCREEN)
      .width(CameraConstants.FULL_SCREEN)
      .backgroundColor(Color.White) // 白色背景
      .padding({
        top: this.uiContext.px2vp(AppStorage.get('topAvoid')) as number,
        bottom: this.uiContext.px2vp(AppStorage.get('bottomAvoid')) as number
      });
    }.hideBackButton(true)
  }
}
相关推荐
2601_949593652 分钟前
基础入门 React Native 鸿蒙跨平台开发:卡片组件
react native·react.js·harmonyos
沐芊屿8 分钟前
华为交换机配置M-LAG
服务器·网络·华为
qq_177767371 小时前
React Native鸿蒙跨平台剧集管理应用实现,包含主应用组件、剧集列表、分类筛选、搜索排序等功能模块
javascript·react native·react.js·交互·harmonyos
qq_177767371 小时前
React Native鸿蒙跨平台自定义复选框组件,通过样式数组实现选中/未选中状态的样式切换,使用链式调用替代样式数组,实现状态驱动的样式变化
javascript·react native·react.js·架构·ecmascript·harmonyos·媒体
向哆哆1 小时前
构建跨端健身俱乐部管理系统:Flutter × OpenHarmony 的数据结构与设计解析
数据结构·flutter·鸿蒙·openharmony·开源鸿蒙
烬头88212 小时前
React Native鸿蒙跨平台采用了函数式组件的形式,通过 props 接收分类数据,使用 TouchableOpacity实现了点击交互效果
javascript·react native·react.js·ecmascript·交互·harmonyos
qq_177767372 小时前
React Native鸿蒙跨平台通过Animated.Value.interpolate实现滚动距离到动画属性的映射
javascript·react native·react.js·harmonyos
向哆哆3 小时前
高校四六级报名管理系统的考试信息模块实现:Flutter × OpenHarmony 跨端开发实践
flutter·开源·鸿蒙·openharmony·开源鸿蒙
qq_177767373 小时前
React Native鸿蒙跨平台实现消息列表用于存储所有消息数据,筛选状态用于控制消息筛选结果
javascript·react native·react.js·ecmascript·harmonyos
ujainu4 小时前
Flutter + OpenHarmony 实战:从零开发小游戏(三)——CustomPainter 实现拖尾与相机跟随
flutter·游戏·harmonyos