在自定义界面扫码功能中,第一次扫码成功后触发Callback回调拿到扫码结果后,继续扫码后无法再次触发Callback回调。
问题代码如下:
.onLoad(async () => {
customScan.start()
.then(async (result: Array<scanBarcode.ScanResult>) => {
// 处理扫码结果
this.showScanResult(result);
});
}) 详情请参考:自定义界面扫码。
注意:本案例进入页面之后需要扫码才能出现重新扫码页面,重新扫码响应快速,因此点击重新扫码之前建议将摄像头远离码图。
示例代码如下:
import { scanCore, scanBarcode, customScan } from '@kit.ScanKit';
import { display } from '@kit.ArkUI';
import { AsyncCallback, BusinessError } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { common, abilityAccessCtrl, PermissionRequestResult } from '@kit.AbilityKit';
const TAG: string = '[Scan Sample]';
@Entry
@Component
struct CustomScanPage {
@State userGrant: boolean = false; // 是否已申请相机权限
@State surfaceId: string = ''; // XComponent组件生成id
@State scanResult: string = ''; // 扫码结果
@State isShowResult: boolean = false; // 是否正在扫码
@State cameraHeight: number = 640; // 设置预览流高度,默认单位:vp
@State cameraWidth: number = 360; // 设置预览流宽度,默认单位:vp
displayHeight: number = 0; // 屏幕高度,单位vp
displayWidth: number = 0; // 屏幕宽度,单位vp
private mXComponentController: XComponentController = new XComponentController();
// 返回自定义扫描结果的回调
private callback: AsyncCallback<Array<scanBarcode.ScanResult>> =
async (error: BusinessError, result: Array<scanBarcode.ScanResult>) => {
if (error) {
hilog.error(0x0001, TAG,
`Failed to get ScanResult by callback. Code: ${error.code}, message: ${error.message}`);
return;
}
this.isShowResult = true;
this.scanResult = JSON.stringify(result);
hilog.info(0x0001, 'TAG',
`Succeeded in getting ScanResult by callback, result is ${JSON.stringify(result)}`);
};
async onPageShow() {
// 自定义启动第一步:用户申请权限
await this.requestCameraPermission();
this.isShowResult = false;
// 多码扫码识别时enableMultiMode设置为true,单码扫码识别时enableMultiMode设置为false
let options: scanBarcode.ScanOptions = {
scanTypes: [scanCore.ScanType.ALL],
enableMultiMode: true,
enableAlbum: true
};
// 自定义启动第二步:设置预览流布局尺寸
this.setDisplay();
try {
// 自定义启动第三步:初始化接口
customScan.init(options);
} catch (error) {
hilog.error(0x0001, TAG, `Failed to init customScan. Code: ${error.code}, message: ${error.message}`);
}
}
async onPageHide() {
// 页面消失或隐藏时停止并释放相机流
this.userGrant = false;
this.customScanStop();
try {
customScan.release().catch((error: BusinessError) => {
hilog.error(0x0001, TAG,
`Failed to release customScan by promise. Code: ${error.code}, message: ${error.message}`);
});
} catch (error) {
hilog.error(0x0001, TAG, `Failed to release customScan. Code: ${error.code}, message: ${error.message}`);
}
}
// 用户申请权限
async reqPermissionsFromUser(): Promise<number[]> {
hilog.info(0x0001, TAG, 'reqPermissionsFromUser start');
let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
let atManager = abilityAccessCtrl.createAtManager();
try {
const grantStatus: PermissionRequestResult =
await atManager.requestPermissionsFromUser(context, ['ohos.permission.CAMERA']);
return grantStatus.authResults;
} catch (error) {
hilog.error(0x0001, TAG, `Failed to requestPermissionsFromUser. Code: ${error.code}, message: ${error.message}`);
return [];
}
}
// 用户申请相机权限
async requestCameraPermission() {
let grantStatus = await this.reqPermissionsFromUser();
for (let i = 0; i < grantStatus.length; i++) {
if (grantStatus[i] === 0) {
hilog.info(0x0001, TAG, `Succeeded in getting permissions.`);
this.userGrant = true;
break;
}
}
}
// 竖屏时获取屏幕尺寸,设置预览流全屏示例
async setDisplay() {
try {
// 默认竖屏
let displayClass = display.getDefaultDisplaySync();
this.displayHeight = this.getUIContext().px2vp(displayClass.height);
this.displayWidth = this.getUIContext().px2vp(displayClass.width);
let maxLen: number = Math.max(this.displayWidth, this.displayHeight);
const RATIO: number = 16 / 9;
this.cameraHeight = maxLen;
this.cameraWidth = maxLen / RATIO;
} catch (error) {
hilog.error(0x0001, TAG, `Failed to getDefaultDisplaySync. Code: ${error.code}, message: ${error.message}`);
}
}
async customScanStop() {
try {
customScan.stop().catch((error: BusinessError) => {
hilog.error(0x0001, TAG, `Failed to stop customScan. Code: ${error.code}, message: ${error.message}`);
});
} catch (error) {
hilog.error(0x0001, TAG, `Failed to stop customScan. Code: ${error.code}, message: ${error.message}`);
}
}
build() {
Stack() {
Column() {
Button('重新扫码')
.margin({ top: 50 })
.onClick(() => {
try {
// 重新触发扫码
customScan.rescan();
this.isShowResult = false;
this.scanResult = '';
} catch (error) {
hilog.error(0x0001, '[Scan Sample]',
`Failed to rescan customScan. Code: ${error.code}, message: ${error.message}`);
}
});
Text(this.scanResult)
.width(250)
.margin({ top: 20 });
}
.width('100%')
.height('100%')
.visibility(this.isShowResult ? Visibility.Visible : Visibility.None);
if (this.userGrant) {
Column() {
XComponent({
id: 'componentId',
type: XComponentType.SURFACE,
controller: this.mXComponentController
})
.onLoad(async () => {
hilog.info(0x0001, TAG, `Succeeded in loading, onLoad is called.`);
// 获取XComponent组件的surfaceId
this.surfaceId = this.mXComponentController.getXComponentSurfaceId();
let viewControl: customScan.ViewControl = {
width: this.cameraWidth,
height: this.cameraHeight,
surfaceId: this.surfaceId
};
try {
// 自定义启动第四步:请求扫码接口,通过Promise方式回调
customScan.start(viewControl, this.callback);
} catch (error) {
hilog.error(0x0001, TAG, `Failed to start customScan. Code: ${error.code}, message: ${error.message}`);
}
})
.width(this.cameraWidth)
.height(this.cameraHeight)
.position({ x: 0, y: 0 });
}
.height('100%')
.width('100%')
.visibility(this.isShowResult ? Visibility.None : Visibility.Visible);
}
}
.width('100%')
.height('100%');
}
}