Since 6.1.1(24), recognition of the Mainland Travel Permit for Hong Kong and Macao Residents and Mainland Travel Permit for Taiwan Residents has been added.
The card recognition control provides structured recognition services for ID cards, vehicle licenses, driver's licenses, passports, bank cards, Mainland Travel Permits for Hong Kong and Macao Residents, and Mainland Travel Permits for Taiwan Residents. Please note that ID card support is currently limited to Chinese second-generation ID cards (excluding Hong Kong SAR, Macao SAR, and Taiwan, China) and excludes bilingual (Han and ethnic minority languages) versions. With the built-in automatic classification feature, the system can automatically identify the card type and return both structured data and card image information.
In scenarios where the information about a certificate (such as an ID card or bank card) needs to be filled in, the card recognition control can be used to read the Optical Character Recognition (OCR) information and return the result. The front and back sides can be identified separately, or both sides can be identified at the same time.
Figure 1 Bank card recognition

Supported languages: simplified Chinese and English
Currently, card recognition supports only cards issued in the Chinese mainland (excluding Hong Kong SAR, Macao SAR, and Taiwan, China), including ID cards, bank cards, passports, driver's licenses, vehicle licenses, Mainland Travel Permits for Hong Kong and Macao Residents, and Mainland Travel Permits for Taiwan Residents.
The aspect ratio of a card must be the same as that of the actual card. The card must not be deformed. The shooting angle must be less than 30 degrees.
The card image must be clear and complete. There is no moire, block, reflection, or card cover.
This control should not be blocked by another component or window.
The following lists only some main APIs called in the demo. For details about all APIs, please refer to the API Reference.
| API | Description |
|---|---|
| CardRecognition | Card recognition control |
| CardRecognitionResult | Card recognition result. |
Add classes related to the card recognition control to a project.
import { CardRecognition, CardRecognitionResult, CardType, CardSide, CardRecognitionConfig, ShootingMode, CardContentConfig, BankCardConfig } from '@kit.VisionKit';
import { hilog } from '@kit.PerformanceAnalysisKit'; Configure a UI layout, select the types and sides of cards to be recognized, set related parameters, and obtain return values through callbacks.
Since 5.1.1(19), the callback parameter in the CardRecognition API has been deprecated. Use onResult instead.
The following are code examples for recognizing ID cards, bank cards, passports, driver's licenses, vehicle licenses, Mainland Travel Permits for Hong Kong and Macao Residents, and Mainland Travel Permits for Taiwan Residents.
const TAG = 'CardRecognition';
@Entry
@Component
struct Index {
build() {
Column() {
// Identity Card
CardRecognition({
supportType: CardType.CARD_ID,
// ID cards can be recognized on both sides.
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%')
}
} const TAG = 'CardRecognition';
@Entry
@Component
struct Index {
build() {
Column() {
// Bank card.
CardRecognition({
supportType: CardType.CARD_BANK,
// One side of a bank card can be recognized.
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%')
}
} const TAG = 'CardRecognition';
@Entry
@Component
struct Index {
build() {
Column() {
// Passport
CardRecognition({
supportType: CardType.CARD_PASSPORT,
// One side of a passport can be recognized.
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%')
}
} const TAG = 'CardRecognition';
@Entry
@Component
struct Index {
build() {
Column() {
// Driver's license.
CardRecognition({
supportType: CardType.CARD_DRIVER_LICENSE,
// Both sides of a driver's license can be recognized.
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%')
}
} const TAG = 'CardRecognition';
@Entry
@Component
struct Index {
build() {
Column() {
// Vehicle license
CardRecognition({
supportType: CardType.CARD_VEHICLE_LICENSE,
// Both sides of a vehicle license can be recognized.
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%')
}
} const TAG = 'CardRecognition';
@Entry
@Component
struct Index {
build() {
Column() {
// Mainland Travel Permit for Hong Kong and Macao Residents
CardRecognition({
supportType: CardType.CARD_MAINLAND_TRAVEL_PERMIT_HK_MO,
// Both sides of the Mainland Travel Permit for Hong Kong and Macao Residents can be recognized.
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%')
}
} const TAG = 'CardRecognition';
@Entry
@Component
struct Index {
build() {
Column() {
// Mainland Travel Permit for Taiwan Residents
CardRecognition({
supportType: CardType.CARD_MAINLAND_TRAVEL_PERMIT_TW,
// Both sides of the Mainland Travel Permit for Taiwan Residents can be recognized.
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%')
}
} // The development example of card recognition is implemented on two screens. One is the entry screen, and the other is the implementation screen.
// The entry screen needs to introduce the implementation screen. In the following example, the implementation screen file name is CardDemoPage.
import { CardDemoPage } from './CardDemoPage';
@Entry
@Component
struct MainPage {
@Provide('pathStack') pathStack: NavPathStack = new NavPathStack();
@Builder
PageMap(name: string) {
if (name === 'cardRecognition') {
CardDemoPage()
}
}
// Button on the card recognition entry screen.
build() {
Navigation(this.pathStack) {
Button('CardRecognition', { stateEffect: true, type: ButtonType.Capsule })
.width('50%')
.height(40)
.onClick(() => {
this.pathStack.pushPath({ name: 'cardRecognition' });
})
}.title('Card recognition control demo').navDestination(this.PageMap)
.mode(NavigationMode.Stack)
}
} // Card recognition implementation screen, and its file name is **CardDemoPage**. This screen needs to be introduced by the entry screen.
import { CardRecognition, CardRecognitionResult, CardType, CardSide, ShootingMode } from '@kit.VisionKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
const TAG: string = 'CardRecognitionPage';
// Card recognition screen, which is used to load uiExtensionAbility.
@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({
// Here, the ID card type is used as an example.
supportType: CardType.CARD_ID,
cardSide: CardSide.DEFAULT,
cardRecognitionConfig: {
defaultShootingMode: ShootingMode.MANUAL,
isPhotoSelectionSupported: true
},
onResult: ((params: CardRecognitionResult) => {
hilog.info(0x0001, TAG, `params code: ${params.code}`);
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)
Text(JSON.stringify(cardData))
.width('100%')
.fontSize(12)
}
}
})
}
.listDirection(Axis.Vertical)
.alignListItem(ListItemAlign.Center)
.margin({
top: 50
})
.width('100%')
.height('100%')
}
}