HarmonyOS 卡证识别开发全攻略:从入门到实战(基于 ArkTS)
本文详细介绍了HarmonyOS卡证识别控件的开发方法。该控件支持身份证、银行卡、护照等5种证件识别,能自动分类并返回结构化信息。开发时需注意:仅支持真机测试、有限证件类型和语种等约束。
在移动应用开发中,手动输入身份证、银行卡等信息不仅效率低,还容易出错。华为 HarmonyOS 提供的卡证识别控件,能通过 OCR 技术自动识别多种证件信息,完美解决这一痛点。本文会用口语化的表达,从场景介绍、约束限制,到详细开发步骤和完整实例,带大家一步步掌握卡证识别开发,每个重点都搭配 ArkTS 代码,让大家看完就能上手实操。
一、先搞懂:卡证识别控件能做啥?
咱们先明确下,这个卡证识别控件可不是花架子,功能实实在在。它能识别多种常见证件,还能自动分类、返回结构化信息,在很多场景都能派上大用场。
1.1 支持的证件类型,看这 5 种就够了
目前控件能搞定 5 种常用证件,基本覆盖日常开发需求。
- 身份证:只支持中国大陆二代身份证,要注意,民汉双文的身份证暂时识别不了。而且它能单独识别正面、反面,也能同时进行双面识别,特别方便。
- 行驶证、驾驶证:这两种证件也支持双面识别,像行驶证上的车辆信息、驾驶证上的准驾车型等,都能准确识别出来。
- 护照:只能识别单面,不过像护照号、有效期、持证人姓名这些关键信息,都能完整提取。
- 银行卡:同样是单面识别,不仅能识别卡号,还能通过配置显示卡号弹窗,让用户确认信息,避免识别错误。
1.2 实用场景,看完就知道在哪用
最常见的场景就是信息自动填充。比如用户注册账号时,需要填写身份证信息,用这个控件扫一下身份证,姓名、身份证号、地址等信息就自动填到表单里了,用户不用再手动输入,既省时间又减少错误。还有绑定银行卡的时候,扫一下银行卡,卡号直接获取,不用用户反复输入再确认,提升用户体验。另外,在一些需要验证证件的场景,比如租车时要验证驾驶证、行驶证,控件能快速识别证件信息并返回,方便开发者进行信息核验。
二、必注意:这些约束限制别踩坑
虽然卡证识别控件很好用,但也有一些约束和限制,开发前一定要了解清楚,不然开发到一半遇到问题,就麻烦了。
2.1 不支持模拟器,必须用真机
这个是硬性要求,不管你是开发哪种证件的识别功能,都不能用模拟器调试,必须用 HarmonyOS 真机。所以开发前,要准备好一台 HarmonyOS 系统的手机或平板,不然根本没办法测试控件是否能正常工作。
2.2 语种和证件类型有局限
从语种来看,目前只支持简体中文和英文,要是遇到其他语种的证件,比如纯日文、韩文的护照,就识别不了了,开发时要考虑到自己的应用是否会涉及这些特殊情况。证件类型方面,前面也提到了,暂时只支持身份证、行驶证、驾驶证、护照、银行卡这 5 种,像社保卡、医保卡这些暂时还不支持,要是应用需要识别这些证件,就不能用这个控件了。
2.3 控件不能被遮挡
在使用卡证识别功能时,卡证识别控件所在的区域不能被其他组件或窗口遮挡。比如你在页面上放了一个弹窗,刚好挡住了卡证识别的取景框,那控件就没办法正常识别证件了。所以开发页面布局时,要确保卡证识别控件的区域是完整显示的,没有其他元素遮挡。
三、手把手教:开发步骤详解(附代码)
了解了场景和约束,接下来就进入重点,教大家一步步进行卡证识别开发,每个步骤都有对应的 ArkTS 代码,跟着做就能实现功能。
3.1 第一步:导入相关类,打好基础
首先,要把卡证识别控件相关的类导入到工程里,这些类是实现卡证识别功能的基础,少了哪个都不行。需要注意的是,CardRecognitionConfig、CardContentConfig、BankCardConfig 这些类从 API12 开始才支持,所以开发时要确保项目的 API 版本不低于 12。
导入代码如下:
import { CardRecognition, CardRecognitionResult, CardType, CardSide, CardRecognitionConfig, ShootingMode, CardContentConfig, BankCardConfig } from "@kit.VisionKit";
import { hilog } from '@kit.PerformanceAnalysisKit';
这里还导入了 hilog,主要是为了在控制台打印日志,方便开发时调试,查看识别结果等信息。
3.2 第二步:配置页面布局,选好识别参数
导入类之后,就要配置页面布局了,同时选择需要识别的卡证类型、卡证页面(正面 / 反面 / 双面),还要设置一些其他的参数,比如拍摄模式、是否支持照片选择等,最后在回调函数里获取识别结果。下面分别以身份证、银行卡、护照、驾驶证、行驶证这 5 种证件为例,给大家展示具体的代码。
3.2.1 身份证识别配置
身份证支持双面识别,所以 cardSide 设为 CardSide.DEFAULT。拍摄模式这里选的是手动模式(ShootingMode.MANUAL),也可以根据需求选自动模式。isPhotoSelectionSupported 设为 true,表示支持从相册选择照片进行识别,要是不需要这个功能,设为 false 就行。
代码如下:
const TAG = 'CardRecognition';
@Entry
@Component
struct Index {
build() {
Column() {
// 身份证识别控件
CardRecognition({
supportType: CardType.CARD_ID, // 识别类型为身份证
cardSide: CardSide.DEFAULT, // 支持双面识别
cardRecognitionConfig: {
defaultShootingMode: ShootingMode.MANUAL, // 手动拍摄模式
isPhotoSelectionSupported: true // 支持从相册选图
},
onResult: ((params: CardRecognitionResult) => {
// 打印识别结果相关日志
hilog.info(0x0001, TAG, `params code: ${params.code}`);
hilog.info(0x0001, TAG, `params cardType: ${params.cardType}`);
hilog.info(0x0001, TAG, `params cardInfo front: ${JSON.stringify(params.cardInfo?.front)}`);
hilog.info(0x0001, TAG, `params cardInfo back: ${JSON.stringify(params.cardInfo?.back)}`);
})
})
}
.height('100%')
.width('100%')
}
}
在 onResult 回调里,params.code 表示识别状态码,200 表示识别成功;params.cardType 是识别出的证件类型;params.cardInfo.front 是身份证正面的信息,像姓名、身份证号等;params.cardInfo.back 是身份证反面的信息,比如有效期。
3.2.2 银行卡识别配置
银行卡只有单面,所以 cardSide 设为 CardSide.FRONT。这里还多了一个 cardContentConfig 配置,isBankNumberDialogShown 设为 true,识别成功后会弹出显示银行卡号的弹窗,让用户确认卡号是否正确,提升信息准确性。
代码如下:
const TAG = 'CardRecognition';
@Entry
@Component
struct Index {
build() {
Column() {
// 银行卡识别控件
CardRecognition({
supportType: CardType.CARD_BANK, // 识别类型为银行卡
cardSide: CardSide.FRONT, // 仅识别正面
cardRecognitionConfig: {
defaultShootingMode: ShootingMode.MANUAL, // 手动拍摄模式
isPhotoSelectionSupported: true, // 支持从相册选图
cardContentConfig: {
bankCard: { isBankNumberDialogShown: true } // 显示卡号弹窗
}
},
onResult: ((params: CardRecognitionResult) => {
hilog.info(0x0001, TAG, `params code: ${params.code}`);
hilog.info(0x0001, TAG, `params cardType: ${params.cardType}`);
hilog.info(0x0001, TAG, `params cardInfo: ${JSON.stringify(params.cardInfo?.main)}`);
})
})
}
.height('100%')
.width('100%')
}
}
银行卡的识别信息存在 params.cardInfo.main 里,包括卡号、银行名称等。
3.2.3 护照识别配置
护照也是单面识别,配置和银行卡类似,只是 supportType 设为 CardType.CARD_PASSPORT,不需要 cardContentConfig 配置(除非有特殊需求)。
代码如下:
const TAG = 'CardRecognition';
@Entry
@Component
struct Index {
build() {
Column() {
// 护照识别控件
CardRecognition({
supportType: CardType.CARD_PASSPORT, // 识别类型为护照
cardSide: CardSide.FRONT, // 仅识别正面
cardRecognitionConfig: {
defaultShootingMode: ShootingMode.MANUAL, // 手动拍摄模式
isPhotoSelectionSupported: true // 支持从相册选图
},
onResult: ((params: CardRecognitionResult) => {
hilog.info(0x0001, TAG, `params code: ${params.code}`);
hilog.info(0x0001, TAG, `params cardType: ${params.cardType}`);
hilog.info(0x0001, TAG, `params cardInfo: ${JSON.stringify(params.cardInfo?.main)}`);
})
})
}
.height('100%')
.width('100%')
}
}
护照的识别信息,像护照号、持证人姓名、有效期等,都在 params.cardInfo.main 中。
3.2.4 驾驶证识别配置
驾驶证支持双面识别,配置和身份证类似,supportType 设为 CardType.CARD_DRIVER_LICENSE。
代码如下:
const TAG = 'CardRecognition';
@Entry
@Component
struct Index {
build() {
Column() {
// 驾驶证识别控件
CardRecognition({
supportType: CardType.CARD_DRIVER_LICENSE, // 识别类型为驾驶证
cardSide: CardSide.DEFAULT, // 支持双面识别
cardRecognitionConfig: {
defaultShootingMode: ShootingMode.MANUAL, // 手动拍摄模式
isPhotoSelectionSupported: true // 支持从相册选图
},
onResult: ((params: CardRecognitionResult) => {
hilog.info(0x0001, TAG, `params code: ${params.code}`);
hilog.info(0x0001, TAG, `params cardType: ${params.cardType}`);
hilog.info(0x0001, TAG, `params cardInfo front: ${JSON.stringify(params.cardInfo?.front)}`);
hilog.info(0x0001, TAG, `params cardInfo back: ${JSON.stringify(params.cardInfo?.back)}`);
})
})
}
.height('100%')
.width('100%')
}
}
驾驶证正面信息(如姓名、准驾车型)在 params.cardInfo.front,反面信息(如有效期、档案编号)在 params.cardInfo.back。
3.2.5 行驶证识别配置
行驶证同样支持双面识别,supportType 设为 CardType.CARD_VEHICLE_LICENSE,其他配置和身份证、驾驶证类似。
代码如下:
const TAG = 'CardRecognition';
@Entry
@Component
struct Index {
build() {
Column() {
// 行驶证识别控件
CardRecognition({
supportType: CardType.CARD_VEHICLE_LICENSE, // 识别类型为行驶证
cardSide: CardSide.DEFAULT, // 支持双面识别
cardRecognitionConfig: {
defaultShootingMode: ShootingMode.MANUAL, // 手动拍摄模式
isPhotoSelectionSupported: true // 支持从相册选图
},
onResult: ((params: CardRecognitionResult) => {
hilog.info(0x0001, TAG, `params code: ${params.code}`);
hilog.info(0x0001, TAG, `params cardType: ${params.cardType}`);
hilog.info(0x0001, TAG, `params cardInfo front: ${JSON.stringify(params.cardInfo?.front)}`);
hilog.info(0x0001, TAG, `params cardInfo back: ${JSON.stringify(params.cardInfo?.back)}`);
})
})
}
.height('100%')
.width('100%')
}
}
行驶证正面的车辆品牌、型号、车牌等信息在 params.cardInfo.front,反面的核定载人数、使用性质等信息在 params.cardInfo.back。
四、实战演练:完整开发实例(入口页 + 实现页)
前面讲的是单个证件的识别配置,实际开发中,通常需要一个入口页,点击按钮进入对应的卡证识别页面,识别完成后还能显示识别到的信息。下面就给大家展示一个完整的开发实例,包含卡证识别入口页和实现页,以身份证识别为例,其他证件的识别只需修改 supportType 等参数即可。
4.1 入口页:MainPage.ets
入口页很简单,就是一个页面,上面有一个 “卡证识别” 按钮,点击按钮跳转到卡证识别实现页(CardDemoPage)。这里用到了 Navigation 和 NavPathStack 来实现页面跳转,这是 HarmonyOS 中常用的页面导航方式。
代码如下:
import { CardDemoPage } from './CardDemoPage'; // 引入识别实现页
@Entry
@Component
struct MainPage {
// 用于管理页面导航栈
@Provide('pathStack') pathStack: NavPathStack = new NavPathStack();
// 页面映射,根据名称跳转到对应的页面
@Builder
PageMap(name: string) {
if (name === 'cardRecognition') {
CardDemoPage(); // 跳转到卡证识别实现页
}
}
build() {
// 导航组件
Navigation(this.pathStack) {
// 卡证识别入口按钮
Button('卡证识别', { stateEffect: true, type: ButtonType.Capsule })
.width('50%')
.height(40)
.onClick(() => {
// 点击按钮,将识别页推入导航栈,实现跳转
this.pathStack.pushPath({ name: 'cardRecognition' });
})
}
.title('卡证识别控件Demo') // 导航栏标题
.navDestination(this.PageMap) // 设置页面映射
.mode(NavigationMode.Stack) // 栈式导航模式
}
}
这里的 @Provide ('pathStack') 是为了给子组件(CardDemoPage)提供导航栈实例,方便子组件进行页面返回操作。Button 的 type 设为 Capsule,是胶囊样式的按钮,看起来更美观;stateEffect 设为 true,点击时有状态变化的效果。
4.2 实现页:CardDemoPage.ets
实现页是卡证识别的核心页面,主要功能是加载卡证识别控件,进行身份证识别,识别成功后将识别到的信息(包括证件图片和文字信息)显示在页面上,要是识别失败(状态码不是 200),就返回入口页。
代码如下:
import { CardRecognition, CardRecognitionResult, CardType, CardSide, ShootingMode } from "@kit.VisionKit";
import { hilog } from '@kit.PerformanceAnalysisKit';
const TAG: string = 'CardRecognitionPage'; // 日志标签
// 卡证识别实现页
@Entry
@Component
export struct CardDemoPage {
// 用于存储识别到的卡证信息
@State cardDataSource: Record<string, string>[] = [];
// 从父组件获取导航栈实例,用于返回入口页
@Consume('pathStack') pathStack: NavPathStack;
build() {
// 导航目标组件,用于承载识别页面内容
NavDestination() {
// 栈式布局,用于叠加显示识别控件和信息列表
Stack({ alignContent: Alignment.Top }) {
// 显示识别到的卡证信息的栈
Stack() {
this.cardDataShowBuilder(); // 调用自定义构建器显示信息
}
.width('80%')
.height('80%')
// 卡证识别控件(身份证识别为例)
CardRecognition({
supportType: CardType.CARD_ID, // 识别类型:身份证
cardSide: CardSide.DEFAULT, // 支持双面识别
cardRecognitionConfig: {
defaultShootingMode: ShootingMode.MANUAL, // 手动拍摄模式
isPhotoSelectionSupported: true // 支持从相册选图
},
onResult: ((params: CardRecognitionResult) => {
// 打印识别状态码
hilog.info(0x0001, TAG, `params code: ${params.code}`);
// 识别失败(状态码非200),返回入口页
if (params.code !== 200) {
this.pathStack.pop();
}
// 打印识别的证件类型
hilog.info(0x0001, TAG, `params cardType: ${params.cardType}`);
// 将身份证正面信息添加到数据源
if (params.cardInfo?.front !== undefined) {
this.cardDataSource.push(params.cardInfo?.front);
}
// 将身份证反面信息添加到数据源
if (params.cardInfo?.back !== undefined) {
this.cardDataSource.push(params.cardInfo?.back);
}
// 其他证件(如银行卡、护照)的信息添加(此处预留)
if (params.cardInfo?.main !== undefined) {
this.cardDataSource.push(params.cardInfo?.main);
}
// 打印身份证正反面信息
hilog.info(0x0001, TAG, `params cardInfo front: ${JSON.stringify(params.cardInfo?.front)}`);
hilog.info(0x0001, TAG, `params cardInfo back: ${JSON.stringify(params.cardInfo?.back)}`);
})
})
}
.width('100%')
.height('100%')
}
.width('100%')
.height('100%')
.hideTitleBar(true) // 隐藏导航栏标题栏,让识别控件全屏显示
}
// 自定义构建器:用于显示识别到的卡证信息
@Builder
cardDataShowBuilder() {
// 列表组件,垂直方向显示信息
List() {
// 遍历数据源,显示每条卡证信息
ForEach(this.cardDataSource, (cardData: Record<string, string>) => {
ListItem() {
Column() {
// 显示证件图片
Image(cardData.cardImageUri)
.objectFit(ImageFit.Contain) // 图片适应方式:包含
.width(100)
.height(100)
// 显示证件文字信息(JSON格式)
Text(JSON.stringify(cardData))
.width('100%')
.fontSize(12) // 字体大小,避免文字过多显示不全
}
}
})
}
.listDirection(Axis.Vertical) // 列表垂直排列
.alignListItem(ListItemAlign.Center) // 列表项居中对齐
.margin({ top: 50 }) // 顶部margin,避免信息靠上显示
.width('100%')
.height('100%')
}
}
4.2.1 关键代码解析
- @State cardDataSource:用 @State 装饰器修饰,是状态变量,当它的值发生变化时,页面会自动刷新,显示最新的识别信息。它是一个数组,每个元素是 Record<string, string> 类型,用来存储单页证件的信息,包括 cardImageUri(证件图片的 URI)和其他文字信息(如姓名、身份证号等)。
- @Consume ('pathStack'):从父组件(MainPage)消费导航栈实例,当识别失败时,调用 this.pathStack.pop () 就能返回入口页。
- CardRecognition 控件:这里设置的是身份证识别,要是想识别其他证件,只需把 supportType 改成对应的类型,比如识别银行卡就改成 CardType.CARD_BANK,同时调整 cardSide 等参数。
- cardDataShowBuilder 构建器:用 List 组件显示识别到的信息,每个 ListItem 包含证件图片和文字信息。Image 组件通过 cardData.cardImageUri 获取证件图片,Text 组件用 JSON.stringify (cardData) 显示所有文字信息,方便开发者查看完整的识别结果。
4.2.2 测试效果
把这两个页面的代码写好后,用 HarmonyOS 真机运行项目。点击入口页的 “卡证识别” 按钮,进入实现页,此时会打开相机,对准身份证正面或反面,手动点击拍摄按钮进行识别。识别成功后,页面会显示身份证的图片和对应的文字信息;要是识别失败,比如相机没对准证件、光线太暗导致识别不清,页面会自动返回入口页。另外,也可以点击页面上的相册图标,从相册选择保存好的身份证图片进行识别,同样能得到识别结果。
五、常见问题与解决办法
在开发和测试过程中,可能会遇到一些问题,这里总结了几个常见的问题和对应的解决办法,帮大家少走弯路。
5.1 问题 1:模拟器运行报错
现象:在模拟器上运行项目,打开卡证识别页面时,报错提示不支持该功能。原因:前面已经提到,卡证识别控件不支持模拟器,只能用真机。解决办法:准备一台 HarmonyOS 系统的真机,将项目部署到真机上进行测试。部署前要确保真机已开启开发者模式,并且已在 DevEco Studio 中正确配置了设备。
5.2 问题 2:识别不到证件信息
现象:用真机测试,对准证件拍摄后,没有返回识别信息,日志中可能显示识别失败。原因:可能有以下几种原因:
- 证件不在支持的类型范围内,比如用了民汉双文的身份证,或者社保卡等不支持的证件。
- 拍摄时光线不好,证件上的文字模糊,导致 OCR 识别不出信息。
- 卡证识别控件被其他组件遮挡,比如页面上有弹窗、按钮等元素挡住了取景框。解决办法:
- 确认使用的是支持的 5 种证件,并且身份证是中国大陆二代非民汉双文的。
- 调整拍摄环境,确保光线充足,证件平整,文字清晰,让证件完全处于取景框内,没有倾斜或超出边框。
- 检查页面布局,确保卡证识别控件所在的区域没有被其他组件遮挡,必要时可以让控件全屏显示。
5.3 问题 3:从相册选图识别失败
现象:点击相册图标,选择证件图片后,识别失败,没有返回信息。原因:可能是图片不符合要求,比如图片分辨率太低、证件在图片中占比太小、图片有旋转或变形等,导致 OCR 无法准确识别。解决办法:选择清晰、分辨率适中的证件图片,确保证件在图片中占比足够大,没有旋转、变形或遮挡,这样能提高识别成功率。
六、总结与扩展
通过本文的介绍,相信大家已经掌握了 HarmonyOS 卡证识别控件的开发方法,从场景了解、约束注意,到开发步骤和完整实例,每个环节都有详细的说明和代码,只要跟着操作,就能实现卡证识别功能。
6.1 开发总结
开发卡证识别功能,核心步骤就是导入相关类、配置控件参数(证件类型、拍摄模式等)、在回调中处理识别结果,最后根据需求显示或使用识别到的信息。需要特别注意的是,必须用真机测试,而且要确保控件不被遮挡,证件类型在支持范围内。
6.2 功能扩展
在实际项目中,还可以对卡证识别功能进行扩展,提升用户体验和功能完整性。比如:
- 增加识别 loading 提示:在点击拍摄或选择图片后,显示 loading 动画,告诉用户正在进行识别,避免用户以为没操作成功而重复点击。
- 信息校验:识别到证件信息后,对关键信息进行校验,比如身份证号可以校验位数和校验码是否正确,银行卡号可以校验格式是否正确,要是校验不通过,提示用户重新识别。
- 多证件切换:在实现页增加证件类型选择按钮,用户可以根据需要选择识别身份证、银行卡、护照等,不用每次都修改代码重新编译。
- 信息编辑:识别到的信息可能存在个别错误(比如识别错了一个数字),可以提供编辑功能,让用户修改错误的信息后再提交。
比如增加多证件切换功能,可以在 CardDemoPage 页面顶部加几个按钮,分别对应不同的证件类型,点击按钮时改变 supportType 的值,重新加载 CardRecognition 控件。代码大致如下:
// 在 CardDemoPage 的 build 方法中,添加证件类型选择按钮
Row({ space: 20 })
.margin({ top: 20 })
.justifyContent(FlexAlign.Center) {
Button('身份证')
.onClick(() => {
this.currentCardType = CardType.CARD_ID;
this.resetRecognition(); // 重置识别控件,重新加载
});
Button('银行卡')
.onClick(() => {
this.currentCardType = CardType.CARD_BANK;
this.resetRecognition();
});
Button('护照')
.onClick(() => {
this.currentCardType = CardType.CARD_PASSPORT;
this.resetRecognition();
});
}
// 然后在 CardRecognition 控件的 supportType 中使用 this.currentCardType
CardRecognition({
supportType: this.currentCardType,
// 其他参数...
})
这样用户就能在页面上自由切换要识别的证件类型,非常方便。
总之,HarmonyOS 的卡证识别控件功能强大,开发难度不大,只要掌握好本文讲的内容,就能轻松在项目中集成该功能,提升用户体验。大家可以根据自己的项目需求,对功能进行扩展和优化,让卡证识别功能更好地服务于应用。
更多推荐


所有评论(0)