HarmonyOS 自定义扫码界面,开启相机流,打开闪光灯,然后手动退到后台,再重新打开,怎么恢复相机流?

如题:HarmonyOS 自定义扫码界面,开启相机流,打开闪光灯,然后手动退到后台,再重新打开,怎么恢复相机流?

阅读 439
1 个回答

1、修改了以下代码,后台到前台已可以正常显示预览流。主要修改点:增加“自定义组件监听页面生命周期”方法,以及在页面关闭的生命周期中增加“停止释放预览流”的代码。

2、具体代码如下,仅供参考:

import { customScan, scanBarcode, scanCore } from '@kit.ScanKit';
import { UIObserver, uiObserver } from '@kit.ArkUI';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { CameraPermissions } from './CameraPermissions';
import GuideToOpenCameraDialog from '../view/dialog/GuideToOpenCameraDialog';
import deviceUtil from '../util/DeviceUtil';

@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(`SubComponent onPageShow`);
        this.onPageShow()
      } else if (info.state === uiObserver.RouterPageState.ON_PAGE_HIDE) {
        console.log(`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('tag--------------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(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(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
  }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进