HarmonyOS 鸿蒙Next 自定义扫码界面如何恢复相机流:开启相机流,打开闪光灯,手动退到后台再重开
HarmonyOS 鸿蒙Next 自定义扫码界面如何恢复相机流:开启相机流,打开闪光灯,手动退到后台再重开
自定义扫码界面,开启相机流,打开闪光灯,然后手动退到后台,再重新打开,怎么恢复相机流
2 回复
1、修改了以下代码 后台到前台已可以正常显示预览流。主要修改点:增加“自定义组件监听页面生命周期”方法,以及在页面关闭的生命周期中增加“停止释放预览流”的代码。从后台到前台 闪光灯直接打开的代码 伙伴可以自己适配
2、具体代码如下,仅供参考:
/**
* 闪光灯界面
*/
import { customScan, scanBarcode, scanCore } from '@kit.ScanKit';
import { CameraPermissions } from './CameraPermissions';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { faceDetector } from '@kit.CoreVisionKit';
import GuideToOpenCameraDialog from '../view/dialog/GuideToOpenCameraDialog';
import deviceUtil from '../util/DeviceUtil';
import { UIObserver, uiObserver } from '@kit.ArkUI';
@Entry
@Component
export struct FlashLightPage {
listener: (info: uiObserver.RouterPageInfo) => void = (info: uiObserver.RouterPageInfo) => {
let routerInfo: uiObserver.RouterPageInfo | undefined = this.queryRouterPageInfo();
if (info.pageId == routerInfo?.pageId) {
if (info.state == uiObserver.RouterPageState.ON_PAGE_SHOW) {
console.log(`bai-------SubComponent onPageShow`);
this.onPageShow()
} else if (info.state == uiObserver.RouterPageState.ON_PAGE_HIDE) {
console.log(`bai-------SubComponent onPageHide`);
this.onPageHide()
}
}
}
/**
* SOS规则 : ...___... 为一组,两组之间有间隔
*/
/**
* SOS求救三短三长三短:三短时间间隔
*/
readonly SOS_SHORT_TIME: number = 300
/**
* SOS求救三短三长三短:三长时间间隔
*/
readonly SOS_LONG_TIME: number = 900
/**
* SOS求救三短三长三短:一组信号完毕后时间间隔
*/
readonly SOS_INTERVAL_TIME = 1800
cameraPermissions: CameraPermissions = new CameraPermissions()
options: scanBarcode.ScanOptions = {
scanTypes: [scanCore.ScanType.ALL],
enableMultiMode: true,
enableAlbum: true
};
// 设置预览流高度,默认单位:vp
@State cameraHeight: number = 100
// 设置预览流宽度,默认单位:vp
@State cameraWidth: number = 100
private mXComponentController: XComponentController = new XComponentController();
@State havaCameraPermission: boolean = false
@State isStartCamera: boolean = false
@State isLightOpen: boolean = false
@State isSosLightOpen: boolean = false
@State intervalId: number = 0
@State sosShortLightTime: number = 0
@State sosLongLightTime: number = 0
@State sosIntervalTime: boolean = false
clickToOpenCamera: boolean = false
@State isReleaseCamera: boolean = false // 是否已释放相机流
//引导用户开启相机权限弹框
toOpenCameraDialog: CustomDialogController = new CustomDialogController({
builder: GuideToOpenCameraDialog({
confirm: () => {
this.clickToOpenCamera = true
deviceUtil.startAppDetail()
},
cancel: () => {
}
}),
autoCancel: false,
alignment: DialogAlignment.Center
})
async aboutToAppear() {
let uiObserver: UIObserver = this.getUIContext().getUIObserver();
uiObserver.on('routerPageUpdate', this.listener);
this.cameraPermissions.setListener({
result: (type: number) => {
if (type === 0) {
this.havaCameraPermission = true
} else {
this.showOpenCameraPermission()
}
}
})
await this.cameraPermissions.getHaveCameraPermission()
}
aboutToDisappear(): void {
let uiObserver: UIObserver = this.getUIContext().getUIObserver();
uiObserver.off('routerPageUpdate', this.listener);
}
showOpenCameraPermission() {
this.toOpenCameraDialog.open()
}
onPageShow(): void {
console.log('bai--------------onPageShow()')
if (this.clickToOpenCamera) {
this.clickToOpenCamera = false
this.cameraPermissions.getHaveCameraPermission()
}else if(this.havaCameraPermission){
this.customScanStart()
}
}
async onPageHide() {
this.releaseCamera();
}
// 释放相机流
async releaseCamera() {
if (!this.isReleaseCamera) {
await this.stopCamera();
await customScan.release();
this.isReleaseCamera = true;
}
}
// 暂停相机流
async stopCamera() {
if (!this.isReleaseCamera) {
customScan.stop();
}
}
build() {
Column() {
Image(this.isLightOpen ? $r('app.media.switch_on') : $r('app.media.switch_off'))
.width(151)
.height(151)
.onClick(() => {
try {
if (this.havaCameraPermission) {
if (this.isSosLightOpen) {
this.clearSosStatus()
if (customScan.getFlashLightStatus()) {
customScan.closeFlashLight();
}
this.isSosLightOpen = false
this.isLightOpen = false
}
// 根据当前闪光灯状态,选择打开或关闭闪关灯
else if (customScan.getFlashLightStatus()) {
customScan.closeFlashLight();
this.isLightOpen = false
} else {
customScan.openFlashLight();
this.isLightOpen = true
}
} else {
this.cameraPermissions.getHaveCameraPermission()
}
} catch (e) {
if (this.havaCameraPermission) {
this.customScanStart()
}
console.log('bai' + e)
}
})
Image(this.isSosLightOpen ? $r('app.media.sos_on_btn') : $r('app.media.sos_off_btn'))
.width(89)
.height(59)
.margin({
top: 15
})
.onClick(() => {
try {
if (this.havaCameraPermission) {
if (this.isSosLightOpen) {
this.clearSosStatus()
if (customScan.getFlashLightStatus()) {
customScan.closeFlashLight();
}
this.isSosLightOpen = false
this.isLightOpen = false
} else {
this.sosShortInterval()
this.isSosLightOpen = true
this.isLightOpen = true
}
} else {
this.cameraPermissions.getHaveCameraPermission()
}
} catch (e) {
if (this.havaCameraPermission) {
this.customScanStart()
}
console.log('bai' + e)
}
})
if (this.havaCameraPermission) {
Stack() {
XComponent({
id: 'componentId',
type: 'surface',
controller: this.mXComponentController
})
.onLoad(() => {
// 获取XComponent的surfaceId
this.customScanStart();
customScan.openFlashLight();
this.isLightOpen = true;
})// 预览流宽、高,默认单位vp,支持px、lpx、vp
.height(this.cameraHeight)
.width(this.cameraWidth)
.position({ x: 0, y: 0 })
}
.alignContent(Alignment.Bottom)
.height(1)
.width(1)
.position({ x: 0, y: 0 })
}
}
.width('100%')
.height('100%')
.backgroundImage($r('app.media.screen_bg'))
.backgroundImageSize({
width: '100%',
height: '100%'
})
.justifyContent(FlexAlign.Center)
}
/**
* 开启相机流
*/
private customScanStart() {
this.isReleaseCamera = false
let surfaceId: string = this.mXComponentController.getXComponentSurfaceId();
// 设置ViewControl相应字段
let viewControl: customScan.ViewControl = {
width: this.cameraWidth,
height: this.cameraHeight,
surfaceId: surfaceId
};
customScan.init(this.options);
customScan.start(viewControl).then((scanResult: Array<scanBarcode.ScanResult>) => {
this.isStartCamera = true;
hilog.info(0x0001, '[Scan Sample]',
`Succeeded in getting ScanResult by promise, scanResult is ${JSON.stringify(scanResult)}`);
}).catch((error: BusinessError) => {
this.isStartCamera = false;
hilog.error(0x0001, '[Scan Sample]',
`Failed to get ScanResult by promise. Code: ${error.code}, message: ${error.message}`);
});
}
//短信号
sosShortInterval() {
this.intervalId = setInterval(() => {
if (this.sosShortLightTime === 3) {
this.sosShortLightTime = 0
clearInterval(this.intervalId)
if (this.sosIntervalTime) {
this.sosInterval()
} else {
this.sosLongInterval()
}
}
if (customScan.getFlashLightStatus()) {
customScan.closeFlashLight()
} else {
customScan.openFlashLight()
this.sosShortLightTime++
}
}, this.SOS_SHORT_TIME)
}
//长信号
sosLongInterval() {
this.intervalId = setInterval(() => {
if (this.sosLongLightTime === 3) {
this.sosLongLightTime = 0
clearInterval(this.intervalId)
this.sosIntervalTime = true
this.sosShortInterval()
}
if (customScan.getFlashLightStatus()) {
customScan.closeFlashLight()
} else {
customScan.openFlashLight()
this.sosLongLightTime++
}
}, this.SOS_LONG_TIME)
}
//一组sos信号完毕之后间隔
sosInterval() {
setTimeout(() => {
this.sosIntervalTime = false
this.sosShortInterval()
}, this.SOS_INTERVAL_TIME)
}
//清空sos 的状态
clearSosStatus() {
clearInterval(this.intervalId)
this.sosIntervalTime = false
this.sosLongLightTime = 0
this.sosShortLightTime = 0
}
}
针对HarmonyOS鸿蒙Next自定义扫码界面恢复相机流的问题,以下是具体操作步骤:
-
开启相机流:
- 在扫码前,确保已调用init接口初始化自定义扫码界面并加载资源。
- 相机流初始化结束后,调用start接口开始扫码。
-
打开闪光灯:
- 调用getFlashLightStatus接口获取闪光灯状态。
- 根据当前光线条件或用户操作,调用openFlashLight接口开启闪光灯。
-
手动退到后台再重开:
- 在应用处于后台时,若需要中断扫码,可调用stop接口控制相机流达到暂停目的。
- 重新打开应用时,调用start接口重新开始扫码。
- 注意,在重新扫码前,建议检查相机权限是否依然有效,以确保扫码功能能够正常使用。
按照以上步骤操作后,通常可以恢复自定义扫码界面的相机流。如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html。