#HarmonyOS NEXT体验官#什么?不用手输身份证信息了? 原创
发现问题
今天又一次实名认证发现大部分软件身份信息的提交还停留在手输阶段,可真是麻烦啊。尤其是对记性比较差的老年人更是一种灾难,手输不仅效率低而且容易出错,有的人还需要对着身份证看着一字一字的输入,效率直接降到最低。
这么聪明的我第一时间想到到的就是身份证识别功能,只需要打开相机一拍照,身份信息就可以识别并且保存,下次使用直接快速复制即可,真是方便快捷,那就在鸿蒙系统实现一个身份证识别功能吧!
开工!
解决问题
开发条件
硬件:支持api12的HarmoneyOS NEXT系统的手机或者平板
软件:DevEco Studio NEXT 5.0.3.403 Api 12语言:方舟编程语言(ArkTs)
UI开发框架:方舟UI框架,ArkUI
功能分析
要实现的卡片的扫描
1. UI界面实现
2. 支持包导入
3. 扫描界面拉起
4. 卡证扫描
5. 卡证识别
6. 卡证内容解析
步骤
1.1首先实现ui界面
先构建一个拉起识别界面的ui界面,方便我们进行后续操作
代码实现如下
@Provide('pathStack') pathStack: NavPathStack = new NavPathStack()
@Builder
PageMap(name: string) {
if (name === 'cardIdentify') {
CardDemoPage()
}
}
build() {
Navigation(this.pathStack) {
Image($r('app.media.card'))
.width('100%')
.height(300)
.objectFit(ImageFit.Fill)
Button('开始识别', { stateEffect: true, type: ButtonType.Capsule })
.width('50%')
.height(40)
.onClick(() => {
this.pathStack.pushPath({ name: 'cardIdentify' })
})
}.title('身份证识别').navDestination(this.PageMap)
.mode(NavigationMode.Stack)
}
2.1将卡证识别控件相关的类添加。
import { CardRecognition, CallbackParam, CardType, CardSide } from "@kit.VisionKit";
配置页面的布局,选择需要识别的卡证类型,和需要识别的卡证页面,在回调中获取结果返回值。
3.1 身份证识别界面拉起
cardSide属性可以设置我们要识别几个面
我们进入源码可以看到如下
FRONT = 0 只扫描人像面
BACK = 1 只扫描国徽面
DEFAULT = 2 正反面都扫描
源码可以看到CardRecognition就是我们要识别卡证的组件了
4.1卡证扫描界面
首先我们先使用某人的身份证进行测试,可以看到组件自身最卡片的识别有一个定位遮罩代码实现如下
Stack({ alignContent: Alignment.Top }) {
Stack() {
this.cardDataShowBuilder()
}
.width('80%')
.height('80%')
CardRecognition({
supportType: CardType.CARD_ID,
cardSide: CardSide.FRONT,
callback: ((params: CallbackParam) => {
hilog.info(0x0001, TAG, `params code: ${params.code}`)
if (params.code === -1) {
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%')
当我们点击拍摄按钮之后
系统api 会在相机页面生成当前识别图片的图层,然后进行识别,(识别回调方法如下)
回调参数
callback: Callback<CallbackParam>;
使用
callback: ((params: CallbackParam) => {
if (params.code === -1) {
this.pathStack.pop()
}
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)
}
})
然后定义一个参数来接收返回的内容
@State cardDataSource: Record<string, string>[] = []
执行程序后可以通过debug发现,返回的数据结构类型如下
根据数据内容我们生成一个对应的实体来接收参数
export class IdentityInfo {
address: string;
birth: string;
cardImageUri: string;
idNumber: string;
name: string;
nationality: string;
originalImageUri: string;
sex: string;
constructor(
address: string,
birth: string,
cardImageUri: string,
idNumber: string,
name: string,
nationality: string,
originalImageUri: string,
sex: string
) {
this.address = address;
this.birth = birth;
this.cardImageUri = cardImageUri;
this.idNumber = idNumber;
this.name = name;
this.nationality = nationality;
this.originalImageUri = originalImageUri;
this.sex = sex;
}
}
生成对应的解析方法,返回一个字符串通过text组件来展示详细信息
getJson(json:string):string{
let txt:IdentityInfo=JSON.parse(json)
let rtTxt:string="人像面信息如下:\n"+
"姓名:"+txt.name+"\n" +
"民族:"+txt.nationality +"\n"+
"性别:"+txt.sex +"\n"+
"卡号:"+txt.idNumber+"\n"+
"地址:"+txt.address+"\n"
return rtTxt
}
Text(this.getJson(JSON.stringify(cardData)))
.width('100%')
.fontSize(12)
这样我们就在鸿蒙中实现了卡证的人像面识别以及数据解析。
如果需要实现正反面的识别,就把cardSide设置为 CardSide.DEFAULT,页面展示如下
这时候数据的接收需要使用list来实现(代码如下)
@Builder
cardDataShowBuilder() {
Column(){
List() {
ForEach(this.cardDataSource, (cardData: Record<string, string>,index:number) => {
ListItem() {
Column() {
Text((JSON.stringify(cardData)))
.width('100%')
.fontSize(12)
}
}
})
}
.listDirection(Axis.Vertical)
.alignListItem(ListItemAlign.Center)
.margin({
top: 50
})
.width('100%')
.height('100%')
}
}
生成的信息如下,然后根据返回的json信息生成对应的实体去解析展示就完成咯
这样可就省事多啦