精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

OpenHarmony應(yīng)用實(shí)現(xiàn)二維碼掃碼識別

系統(tǒng) OpenHarmony
本文就以橘子購物示例應(yīng)用為例,來講解OpenHarmony應(yīng)用二維碼開發(fā)相關(guān)的技術(shù)點(diǎn)。

想了解更多關(guān)于開源的內(nèi)容,請?jiān)L問:

51CTO 開源基礎(chǔ)軟件社區(qū)

https://ost.51cto.com

概念介紹

二維碼的應(yīng)用場景非常廣泛,在購物應(yīng)用中,消費(fèi)者可以直接掃描商品二維碼,瀏覽并購買產(chǎn)品,如圖是購物應(yīng)用的掃描二維碼的頁面。

本文就以橘子購物示例應(yīng)用為例,來講解OpenHarmony應(yīng)用二維碼開發(fā)相關(guān)的技術(shù)點(diǎn)。

我們先看下二維碼相關(guān)的幾個(gè)概念。

  • 二維碼生成

OpenHarmony應(yīng)用框架提供了QRCode組件,用于顯示單個(gè)二維碼的組件。該組件只能用于顯示二維碼,無法顯示條碼與解析碼內(nèi)容。

  • 二維碼解析

OpenHarmony提供了功能強(qiáng)大的三方庫 @ohos/zxing,是一個(gè)解析/生成一維碼/二維碼的庫。詳細(xì)內(nèi)容可以參考@ohos/zxing。

二維碼解析時(shí),通常有兩種方式,使用相機(jī)拍攝獲取圖片或打開相冊選取圖片,然后圖片解析合適的圖片格式,進(jìn)行二維碼解析。

橘子購物示例應(yīng)用掃描二維碼的示例圖:

OpenHarmony應(yīng)用實(shí)現(xiàn)二維碼掃碼識別-開源基礎(chǔ)軟件社區(qū)OpenHarmony應(yīng)用實(shí)現(xiàn)二維碼掃碼識別-開源基礎(chǔ)軟件社區(qū)

配置文件

了解了二維碼相關(guān)的概念后,我們看下橘子購物示例應(yīng)用的oh-package.json5配置文件。

在橘子購物示例應(yīng)用中,實(shí)現(xiàn)首頁二維碼掃描的頁面的文件位置為:entry/src/main/ets/pages/ScanPage.ets。文件內(nèi)容如下:

import { QRCodeScanComponent } from "@ohos/scan-component"
@Entry
@Component
struct Scan {
  build() {
    Column() {
      QRCodeScanComponent()
    }
  }
}

內(nèi)容非常簡單,主要是導(dǎo)入的自定義組件QRCodeScanComponent,這個(gè)組件的代碼來自:二維碼掃描示例應(yīng)用,后文我們這樣分析如何開發(fā)這個(gè)二維碼掃描應(yīng)用。

從這一行,可以了解到OpenHarmony應(yīng)用如何引用ohpm本地三方庫。

"@ohos/scan-component": "file:../libs/ohos-qr-code-scan-1.0.1.har",

oh-package.json5配置文件片段如下:

{
  "license": "ISC",
  "devDependencies": {},
  "name": "product",
  "description": "example description",
  "repository": {},
  "version": "1.0.0",
  "dependencies": {
    "@ohos/http": "file:../libs/ohos-http-1.0.0.tgz",
    "@ohos/video-component": "file:../libs/ohos-video-component-1.0.5.tgz",
    "@ohos/details-page-component": "file:../feature/detailPage",
    "@ohos/notification": "file:../libs/ohos-notification-1.0.0.tgz",
    "@ohos/scan-component": "file:../libs/ohos-qr-code-scan-1.0.1.har",
    "@ohos/updatedialog": "file:../libs/ohos-updatedialog-1.0.0.tgz",
    "@ohos/enter-animation": "file:../libs/ohos-enter-animation-1.0.1.tgz",
    "@ohos/share-component": "file:../libs/ohos-sharecomponent-1.0.1.tgz",
    "@ohos/emitter": "file:../feature/emitter",
    "@ohos/navigation-component": "file:../feature/navigationHome"
  }
}

開發(fā)步驟

我們來看二維碼掃描功能是如何開發(fā)的。

導(dǎo)入ohpm三方庫

在開發(fā)前,我們需要導(dǎo)入ohpm組件庫:@ohos/zxing。可以使用命令行方式導(dǎo)入ohpm install @ohos/zxing,也可以直接在文件entry\oh-package.json5中配置,如文件片段所示。

可以看出,二維碼掃描的核心代碼存放在Feature目錄,是一個(gè)獨(dú)立的module模塊,方便復(fù)用:

“@ohos/feature-qr-code-scan”: “file:…/Feature”。

文件entry\oh-package.json5片段:

"dependencies": {
    "@ohos/feature-qr-code-scan": "file:../Feature",
    "@ohos/zxing": "^2.0.0"
  }

相機(jī)服務(wù)

CameraService.ets文件相機(jī)服務(wù)構(gòu)造函數(shù)中,會(huì)創(chuàng)建一個(gè)圖片接收器。

該圖片接收器可以監(jiān)聽’imageArrival’事件,當(dāng)相機(jī)拍照時(shí)會(huì)觸發(fā)該事件。在監(jiān)聽事件的回調(diào)函數(shù)里,實(shí)現(xiàn)對拍照的圖片進(jìn)行處理。

CameraService.ets文件相機(jī)服務(wù)構(gòu)造函數(shù):

constructor(imgReceiver?: image.ImageReceiver) {
    if (imgReceiver === undefined) {
      this.imageReceiver = image.createImageReceiver(QRCodeScanConst.IMG_DEFAULT_SIZE.WIDTH,
      QRCodeScanConst.IMG_DEFAULT_SIZE.HEIGHT, image.ImageFormat.JPEG, QRCodeScanConst.MAX_IMAGE_CAPACITY)
    } else {
      this.imageReceiver = image.createImageReceiver(imgReceiver.size.width, imgReceiver.size.height,
      imgReceiver.format, imgReceiver.capacity)
    }
  }

在CameraService.ets文件創(chuàng)建相機(jī)函數(shù)中,主要包含如下幾個(gè)步驟:

  • 獲取支持的相機(jī)

根據(jù)context獲取CameraManager,然后獲取支持的相機(jī)(攝像頭)。如果沒有支持的相機(jī),則然后。

如有支持的相機(jī),則默認(rèn)使用相機(jī)列表中的第一個(gè)。實(shí)際應(yīng)用中,對于二維碼掃描,需要使用后置相機(jī)攝像頭。

  • 獲取相機(jī)輸入輸出流

首先,根據(jù)指定的相機(jī),創(chuàng)建相機(jī)輸入流this.cameraInput。

然后,獲取相機(jī)的cameraOutputCapability參數(shù),接著創(chuàng)建兩個(gè)輸出流:

  • 預(yù)覽輸出流

創(chuàng)建相機(jī)預(yù)覽輸出流this.previewOutput,使用的surfaceId來自XComponent組件。預(yù)覽輸出流,對應(yīng)相機(jī)拍照前的圖片預(yù)覽。

  • 相片輸出流

創(chuàng)建相片輸出流this.photoOutput,使用的receivingSurfaceId來自上文創(chuàng)建的圖片接收器。相片輸出流,用于保存到相片。

  • 配置相機(jī)會(huì)話

配置相機(jī)會(huì)話,也比較簡單,添加輸入流和輸出流即可,見代碼及其注釋。

CameraService.ets文件創(chuàng)建相機(jī)函數(shù):

/**
   * 創(chuàng)建相機(jī)
   */
  async createCamera(surfaceId: string) {
    Logger.info("createCamera start")
    // 根據(jù)context獲取CameraManager
    let cameraManager = camera.getCameraManager(AppStorage.Get('context'))
    // 獲取Camera對象數(shù)組
    let cameras = cameraManager.getSupportedCameras()
    // 沒有相機(jī)就停止
    if (cameras.length === 0) {
      Logger.error("createCamera: cameras length is 0.")
      return
    }
    // 拿到相機(jī)列表中的第一個(gè)默認(rèn)相機(jī)id, 根據(jù)id獲取相機(jī)輸入流
    this.cameraInput = cameraManager.createCameraInput(cameras[0])
    this.cameraInput.open()
    // 獲取cameraOutputCapability參數(shù)
    let cameraOutputCapability = cameraManager.getSupportedOutputCapability(cameras[0])
    // 獲取相機(jī)輸出流
    this.previewOutput = cameraManager.createPreviewOutput(cameraOutputCapability.previewProfiles[0], surfaceId)
    // 獲取一個(gè)可以創(chuàng)建相片輸出流的id
    let receivingSurfaceId = await this.imageReceiver.getReceivingSurfaceId()
    // 創(chuàng)建相片輸出流
    this.photoOutput = cameraManager.createPhotoOutput(cameraOutputCapability.photoProfiles[0], receivingSurfaceId)
    // 獲取捕獲會(huì)話的實(shí)例
    this.captureSession = cameraManager.createCaptureSession()
    // 開始會(huì)話配置
    this.captureSession.beginConfig()
    // 使用相機(jī)輸入流---添加一個(gè)攝像頭輸入流
    this.captureSession.addInput(this.cameraInput)
    // 使用相機(jī)輸出流---添加一個(gè)攝像頭輸出
     this.captureSession.addOutput(this.previewOutput)
    // 使用相片輸出流---添加相機(jī)照片的輸出
    this.captureSession.addOutput(this.photoOutput)
    // 結(jié)束并提交配置
    await this.captureSession.commitConfig()
    // 開始捕獲會(huì)話
    await this.captureSession.start()
    Logger.info("createCamera end")
  }

CameraService.ets文件拍照函數(shù)中,指定相片參數(shù)設(shè)置,然后調(diào)用capture()函數(shù)完成拍照。

拍照后會(huì)觸發(fā)圖片接收器的’imageArrival’事件。拍照函數(shù)在使用相機(jī)掃描二維碼的時(shí)候調(diào)用。

該圖片接收器可以監(jiān)聽’imageArrival’事件,當(dāng)相機(jī)拍照時(shí)會(huì)觸發(fā)該事件。在監(jiān)聽事件的回調(diào)函數(shù)里,實(shí)現(xiàn)對拍照的圖片進(jìn)行處理。

CameraService.ets文件拍照函數(shù):

takePicture() {
    let photoSetting = {
      rotation: camera.ImageRotation.ROTATION_0,
      quality: camera.QualityLevel.QUALITY_LEVEL_MEDIUM,
      mirror: false
    }
    this.photoOutput.capture(photoSetting)
  }

二維碼解析實(shí)現(xiàn)代碼

二維碼解析類文件為:QRCodeParser.ets,支持拍照識別二維碼,還支持從相冊選擇二維碼圖片進(jìn)行識別。

我們首先看下如何解析從相機(jī)獲取的二維碼圖片,對應(yīng)函數(shù)為:parseQRCodeImageFromCamera,該類指定一個(gè)時(shí)間隨機(jī)的圖片文件名,圖片歸檔格式,然后繼續(xù)調(diào)用函數(shù)parseQRCodeImageWithNameFromCamera。

/**
   * 解析從相機(jī)獲取的二維碼圖片
   *
   * @param cameraService
   * @param canvasContext
   */
  parseQRCodeImageFromCamera(cameraService: CameraService,
                             imageComponentType?: image.ComponentType): void {
    Logger.info("parseQRCodeImageFromCamera start")
    let fileName = this.getRandomFileName(QRCodeScanConst.IMG_FILE_PREFIX, QRCodeScanConst.IMG_SUFFIX_JPG)
    this.parseQRCodeImageWithNameFromCamera(cameraService, fileName, imageComponentType);
    Logger.info("parseQRCodeImageFromCamera end")
  }

在函數(shù)parseQRCodeImageWithNameFromCamera中,注冊圖片接收器監(jiān)聽’imageArrival’事件,在監(jiān)聽函數(shù)里,對二維碼圖片進(jìn)行解析識別。

當(dāng)相機(jī)對二維碼拍照后,二維碼圖片會(huì)被保存到指定的目錄下,返回文件URI。保存圖片的函數(shù)createPublicDirFileAsset的實(shí)現(xiàn),可以自行查閱源碼。

根據(jù)返回的圖片URI,調(diào)用函數(shù)parseImageQRCode對二維碼進(jìn)行解析。函數(shù)parseImageQRCode后文會(huì)介紹。

如果解析失敗,彈窗提示解析失敗。如果解析成功,會(huì)被解析結(jié)果保存到AppStorage。

保存到AppStorage的二維碼解析結(jié)果會(huì)被@watch裝飾器的變量監(jiān)視,當(dāng)監(jiān)視到有二維碼識別結(jié)果后,會(huì)在界面展示,后文會(huì)介紹。

QRCodeParser.ets文件parseQRCodeImageWithNameFromCamera函數(shù)代碼:

/**
   * 解析從相機(jī)獲取的二維碼圖片,指定文件名稱
   *
   * @param cameraService
   * @param canvasContext
   */
  parseQRCodeImageWithNameFromCamera(cameraService: CameraService,
                                     fileDisplayName: string,
                                     imageComponentType?: image.ComponentType): void {
    Logger.info("parseQRCodeImageWithNameFromCamera...")
    cameraService.imageReceiver.on('imageArrival', async () => {
      Logger.info("parseQRCodeImageWithNameFromCamera imageArrival start")
      // 從接收器獲取下一個(gè)圖像,并返回結(jié)果
      let targetImage: image.Image = await cameraService.imageReceiver.readNextImage()
      // 默認(rèn)按JPEG格式處理
      let imgComponentType = imageComponentType === undefined ? image.ComponentType.JPEG : imageComponentType
      let imageComponent = await targetImage.getComponent(imgComponentType)
      // 將image的ArrayBuffer寫入指定文件中,返回文件uri
      let imageUri = await this.createPublicDirFileAsset(fileDisplayName, mediaLibrary.MediaType.IMAGE,
                     mediaLibrary.DirectoryType.DIR_IMAGE, imageComponent.byteBuffer);
      // 釋放已讀取的image資源,以便處理下一個(gè)資源
      await targetImage.release()

      // 解析二維碼
      let qrCodeParseRlt = await this.parseImageQRCode(imageUri);
      if (!qrCodeParseRlt.isSucess) {
        Logger.error("parseQRCodeImageWithNameFromCamera qrCodeParseRlt is null")
        prompt.showToast({
          message: $r('app.string.qrCodeNotRecognized')
        })
        return;
      }
      // 拼接解析結(jié)果
      AppStorage.SetOrCreate(QRCodeScanConst.QR_CODE_PARSE_RESULT, qrCodeParseRlt.decodeResult);
      Logger.info("parseQRCodeImageWithNameFromCamera imageArrival end")
    })
  }

二維碼解析類文件為:QRCodeParser.ets,支持拍照識別二維碼,還支持從相冊選擇二維碼圖片進(jìn)行識別。

我們接著,再看下如何解析從相冊里挑選的二維碼圖片。

參數(shù)imageSrc為選定圖片的URI地址。

getImageSource()代碼可以自行查詢,實(shí)現(xiàn)根據(jù)圖片URI返回圖片的寬、高,以及圖片的pixelMap數(shù)據(jù)。然后,把像素?cái)?shù)據(jù)寫入ArrayBuffer,供zxing二維碼識別程序使用。

函數(shù)RGBLuminanceSource、BinaryBitmap、BinaryBitmap等都是zxing的類。通過調(diào)用MultiFormatReader的decode函數(shù)對二維碼圖像進(jìn)行解析。

如果解析成功,會(huì)返回成功的標(biāo)記和解析的結(jié)果。

如果解析失敗,會(huì)在catch語句塊里進(jìn)行處理,會(huì)返回失敗的標(biāo)記和解析失敗的原因。

QRCodeParser.ets文件parseImageQRCode函數(shù)代碼:

/**
   * 解析圖片二維碼信息
   * @param canvasContext
   * @param imageSrc
   */
  async parseImageQRCode(imageSrc: string): Promise<DecodeResultAttribute> {
    Logger.info(`parseImageQRCode start`);
    // 獲取圖片的寬高
    let imageSource = await this.getImageSource(imageSrc);
    let imageWidth = imageSource.width;
    let imageHeight = imageSource.height;
    // 獲取PixelMap圖片數(shù)據(jù)
    let pixMapData = imageSource.pixelMap;
    let pixelBytesNumber = pixMapData.getPixelBytesNumber();
    let arrayBuffer: ArrayBuffer = new ArrayBuffer(pixelBytesNumber);
    // 讀取圖像像素?cái)?shù)據(jù),結(jié)果寫入ArrayBuffer里
    await pixMapData.readPixelsToBuffer(arrayBuffer);
    let int32Array = new Int32Array(arrayBuffer);
    let luminanceSource = new RGBLuminanceSource(int32Array, imageWidth, imageHeight);
    let binaryBitmap = new BinaryBitmap(new HybridBinarizer(luminanceSource));
    let mltiFormatReader = new MultiFormatReader();
    let hints = new Map();
    hints.set(DecodeHintType.POSSIBLE_FORMATS, [BarcodeFormat.QR_CODE]);
    mltiFormatReader.setHints(hints);
    try {
      // 解析二維碼
      let decodeResult = mltiFormatReader.decode(binaryBitmap);
      let decodeText = decodeResult.getText();
      Logger.info(`parseImageQRCode end ${decodeText}`);
      return { isSucess: true, decodeResult: decodeText };
    } catch (err) {
      let error = `The error is ${err}`;
      Logger.info(`parseImageQRCode end`);
      return { isSucess: false, decodeResult: error };
    }
  }

相機(jī)掃描識別二維碼

在文件QRCodeScanComponent.ets中實(shí)現(xiàn)了二維碼掃描自定義組件。我們看下該文件中如何實(shí)現(xiàn)相機(jī)掃描二維碼的。

在二維碼掃描組件的aboutToAppear()函數(shù)調(diào)用的watchCameraPermission()函數(shù),用于使用相機(jī)掃描二維碼進(jìn)行識別。

在watchCameraPermission()函數(shù)中,使用setInterval函數(shù)每100ms判斷下是否具有相機(jī)權(quán)限,當(dāng)有相機(jī)權(quán)限的時(shí)候,才能使用相機(jī)掃描二維碼。

當(dāng)具備相機(jī)權(quán)限時(shí) ,使用setInterval函數(shù)每4000ms輪詢判斷下是否識別到二維碼圖片,如果識別到則取消執(zhí)行輪詢。

如果沒有識別到二維碼,則繼續(xù)調(diào)用函數(shù)takePicture()拍照。調(diào)用該函數(shù)后,會(huì)觸發(fā)圖片接收器的監(jiān)聽事件’imageArrival’,對這個(gè)事件的監(jiān)聽分析,見上文。

文件QRCodeScanComponent.ets中,相機(jī)拍照識別二維碼的代碼片段:

aboutToAppear() {
// 監(jiān)聽相機(jī)權(quán)限
this.watchCameraPermission()
// 設(shè)置掃描動(dòng)畫
this.setQRCodeScanAnimation()
// 解析二維碼圖片信息
this.qrCodeParser.parseQRCodeImageFromCamera(this.cameraService);
}
......
// 監(jiān)聽相機(jī)權(quán)限變化
watchCameraPermission() {
let interval = setInterval(() => {
  this.hasCameraPermission = AppStorage.Get(QRCodeScanConst.HAS_CAMERA_PERMISSION)
  if (this.hasCameraPermission) {
	let qrCodeScanInterval = setInterval(() => {
	  if (this.qrCodeParseResult.length > 0 || this.isQRCodeScanStopped) {
		clearInterval(qrCodeScanInterval)
	  }
	  // 拍照
	  this.cameraService.takePicture()
	}, 4000)
	clearInterval(interval)
  }
}, 100)
}

識別相冊二維碼圖片

在文件QRCodeScanComponent.ets中實(shí)現(xiàn)了二維碼掃描自定義組件。我們看下該文件中如何識別相冊二維碼圖片。

首先,設(shè)置this.isQRCodeScanStopped為true,這個(gè)會(huì)關(guān)閉相機(jī)拍照識別二維碼。

然后,通過startAbilityForResult啟動(dòng)相冊應(yīng)用,供用戶選擇二維碼圖片。

如果選擇圖片失敗,則彈窗報(bào)錯(cuò)。

如果選擇圖片成功,則調(diào)用二維碼解碼函數(shù)parseImageQRCode完成對圖片二維碼的識別。

如果識別二維碼成功,則彈窗展示二維碼結(jié)果。

如果識別識別,則toast展示:未識別到二維碼。

文件QRCodeScanComponent.ets中,相冊選擇二維碼圖片進(jìn)行識別代碼片段:

Image($r('app.media.scan_photo'))
  .width(30)
  .height(30)
  .id('scanPhoto')
  .onClick(async () => {
	// 打開相冊獲取圖片
	this.isQRCodeScanStopped = true
	let context = AppStorage.Get('context') as common.UIAbilityContext
	await context.startAbilityForResult({
	  parameters: { uri: 'singleselect' },
	  bundleName: 'com.ohos.photos',
	  abilityName: 'com.ohos.photos.MainAbility',
	}).then(data => {
	  // 獲取want數(shù)據(jù)
	  let want = data['want'];
	  if (want) {
		// param代表want參數(shù)中的paramters
		let param = want['parameters'];
		if (param) {
		  // 被選中的圖片路徑media/image/8
		  let selectedUri = param['select-item-list'];
		  setTimeout(async () => {
			if (!selectedUri) {
			  prompt.showToast({
				message: $r('app.string.queryImageFailed'),
				duration: 1000
			  })
			  return;
			}
			// 獲取解析數(shù)據(jù)
			let qrCodeParseRlt = await this.qrCodeParser.parseImageQRCode(selectedUri[0]);
			if (qrCodeParseRlt.isSucess) {
			  prompt.showDialog({
				title: $r('app.string.qrcodeResult'),
				message: qrCodeParseRlt.decodeResult
			  })
			} else {
			  prompt.showToast({
				message: $r('app.string.qrCodeNotRecognized')
			  })
			}
		  }, 50)
		}
	  }
	})
  })

二維碼掃描組件界面

在文件QRCodeScanComponent.ets中實(shí)現(xiàn)了二維碼掃描自定義組件。我們看下二維碼掃描組件的頁面布局。

整個(gè)頁面使用Stack進(jìn)行堆疊布局。

如果有相機(jī)權(quán)限,會(huì)XComponent組件,用于展示相機(jī)的預(yù)覽輸出流。XComponent組件的onLoad函數(shù)里會(huì)創(chuàng)建相機(jī),onDestroy函數(shù)里會(huì)釋放相機(jī)。

Image($r('app.media.scan_border'))圖片就是二維碼掃描框,引導(dǎo)用戶把二維碼放到框內(nèi)進(jìn)行掃描識別。

Divider是個(gè)分割線,該分割線使能了動(dòng)畫效果,在識別二維碼的過程中,分割線從二維碼識別框里從上到下移動(dòng)。掃描動(dòng)畫實(shí)現(xiàn)代碼如下:

// 掃描掃描動(dòng)畫
  setQRCodeScanAnimation() {
    setInterval(() => {
      animateTo({
        duration: 1000, // 動(dòng)畫時(shí)間
        tempo: 0.5, // 動(dòng)畫速率
        curve: Curve.EaseInOut,
        delay: 200, // 動(dòng)畫延遲時(shí)間
        iterations: -1, // 動(dòng)畫是否重復(fù)播放
        playMode: PlayMode.Normal,
      }, () => {
        this.animationOrdinate = 390 // 掃描動(dòng)畫結(jié)束Y坐標(biāo)
      })
    }, 2000)
  }

Text($r('app.string.putTheQRCodeToScan'))引導(dǎo)用戶把二維碼放到框內(nèi)進(jìn)行掃描識別。

Image($r('app.media.scan_back'))返回退出應(yīng)用。

Image($r('app.media.scan_photo'))從相冊里挑選二維碼圖片進(jìn)行識別。

build() {
Column() {
  Stack() {
	if (this.hasCameraPermission) {
	  XComponent({
		id: 'componentId',
		type: 'surface',
		controller: this.xComponentController
	  })
		.onLoad(() => {
		  // 適配可能需要獲取設(shè)備信息
		  this.xComponentController.setXComponentSurfaceSize({
			surfaceWidth: QRCodeScanConst.IMG_DEFAULT_SIZE.WIDTH,
			surfaceHeight: QRCodeScanConst.IMG_DEFAULT_SIZE.HEIGHT
		  })
		  this.surFaceId = this.xComponentController.getXComponentSurfaceId()
		  this.cameraService.createCamera(this.surFaceId)
		})
		.onDestroy(() => {
		  this.cameraService.releaseCamera()
		})
		.height('100%')
		.width('100%')
	}
	Column() {
	  Column() {
		Image($r('app.media.scan_border'))
		......
		Divider()
		  .strokeWidth(1)
		  .height(4)
		  .width('100%')
		  .color(Color.White)
		  .width('100%')
		  .position({ x: 0, y: 0 })
		  .translate({ x: 0, y: this.animationOrdinate })
	  }
	......
	  Text($r('app.string.putTheQRCodeToScan'))
	......
	}
	......
	Row() {
	  Image($r('app.media.scan_back'))
	  ......
	  Row({ space: 16 }) {
		Image($r('app.media.scan_photo'))
		......
}

運(yùn)行測試效果

可以下載橘子購物示例應(yīng)用代碼,使用DevEco Studio編譯構(gòu)建,使用Simulator模擬器或者真實(shí)設(shè)備進(jìn)行運(yùn)行體驗(yàn)。可以體驗(yàn)下使用相機(jī)對二維碼圖片進(jìn)行識別,還可以嘗試下識別相冊中的二維碼圖片。

git init
git config core.sparsecheckout true
echo code/Solutions/Shopping/OrangeShopping/ > .git/info/sparse-checkout
git remote add origin https://gitee.com/openharmony/applications_app_samples.git
git pull origin master

注意事項(xiàng)

當(dāng)前二維碼示例應(yīng)用識別相冊的二維碼,彈出識別結(jié)果后,程序會(huì)崩潰,已經(jīng)提單跟蹤。示例程序待改進(jìn)。

使用相機(jī)功能直接拍攝二維碼的功能,一直沒有成功運(yùn)行,需要進(jìn)一步優(yōu)化。

想了解更多關(guān)于開源的內(nèi)容,請?jiān)L問:

51CTO 開源基礎(chǔ)軟件社區(qū)

https://ost.51cto.com

責(zé)任編輯:jianghua 來源: 51CTO 開源基礎(chǔ)軟件社區(qū)
相關(guān)推薦

2024-06-26 08:46:45

2023-11-17 09:07:51

.NET生成二維碼識別二維碼

2011-12-06 16:40:45

二維碼快拍二維碼靈動(dòng)快拍

2023-11-17 15:44:06

C++庫生成二維碼

2013-01-30 12:16:49

二維碼NFC近場通訊

2013-12-03 10:32:52

2024-03-07 07:59:37

2021-09-08 10:02:56

面試二維碼前端

2023-05-09 20:41:00

網(wǎng)絡(luò)詐騙網(wǎng)絡(luò)安全

2013-03-27 16:13:17

Android開發(fā)Android二維碼生QR生成

2013-11-19 16:06:39

2017-02-21 09:17:46

二維碼漏洞

2018-03-05 18:39:25

2013-11-26 09:54:02

2011-11-24 16:00:23

信息圖QR碼二維碼

2021-04-09 15:55:07

掃碼支付二維碼數(shù)字人民幣

2024-11-20 13:00:02

2015-10-28 13:33:50

二維碼條形碼掃描源碼

2020-10-08 18:48:02

二維碼安全應(yīng)用安全網(wǎng)絡(luò)攻擊

2014-03-05 14:41:55

二維碼登錄
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

毛片在线不卡| 中文字幕av无码一区二区三区| 亚洲成人影音| 激情av一区二区| 国产一区二区不卡视频| 日韩人妻精品中文字幕| 欧美韩日一区| 亚洲第一天堂无码专区| 十八禁视频网站在线观看| 黄视频在线观看免费| 精品一区二区av| 欧美亚洲国产视频| 尤物在线免费视频| 亚洲素人在线| 精品免费视频.| 深夜黄色小视频| 女人让男人操自己视频在线观看 | 亚洲一区欧美二区| 色偷偷888欧美精品久久久 | 中文久久乱码一区二区| 粉嫩精品一区二区三区在线观看| 久久久蜜桃一区二区| 中文视频一区| 曰本色欧美视频在线| 在线精品视频播放| 性欧美video另类hd尤物| 精品国产1区2区| 国产 国语对白 露脸| 黄色美女网站在线观看| 成人av综合一区| 成人免费视频在线观看超级碰| 亚洲久久在线观看| 欧美日韩一区自拍| 色婷婷综合成人| 三上悠亚影音先锋| 卡通动漫国产精品| 日韩精品一区二区三区swag | 三级在线免费观看| av在线播放网站| 26uuu国产日韩综合| 99影视tv| 国产福利小视频| 久久精品国产网站| 国产精品成久久久久三级| 在线观看亚洲欧美| 亚洲二区免费| 久久久免费电影| 青青草免费av| 综合亚洲视频| 欧美成人高清视频| 无码人妻精品中文字幕| 日韩电影一区| 日韩视频在线免费观看| 日韩不卡av在线| 清纯唯美日韩| 中文字幕欧美在线| 老熟妇一区二区| 国产精品一区2区3区| 亚洲另类图片色| 精品无码在线视频| 亚洲成aⅴ人片久久青草影院| 亚洲黄色在线看| 深爱五月激情网| 国产精品免费大片| 中文字幕日韩av电影| 亚洲综合第一区| 成人在线免费观看网站| 日韩在线观看免费全| 激情无码人妻又粗又大| 久久久久久久久国产一区| xxxxx91麻豆| 青春草免费视频| 亚洲二区在线| 国产精品国产三级国产专播精品人 | 亚洲成人www| 日韩欧美一区二| 免费观看亚洲| 精品视频一区二区三区免费| 手机在线国产视频| 77成人影视| 国产视频亚洲精品| 青青草华人在线视频| 先锋资源久久| 97超级碰碰人国产在线观看| 怡红院av久久久久久久| 另类欧美日韩国产在线| 91久色国产| 外国精品视频在线观看 | 久久超碰亚洲| 9色在线视频网站| 亚洲精品久久7777| 无码aⅴ精品一区二区三区浪潮| 欧美日韩美女| 欧美一区二区三区播放老司机| 国产艳妇疯狂做爰视频| 国产91精品对白在线播放| 最好看的2019年中文视频| 欧美精品入口蜜桃| 性欧美暴力猛交另类hd| 91精品在线观看视频| 日韩中文字幕免费观看| 中文字幕av不卡| 97视频久久久| 亚洲人成777| 日韩av在线电影网| 你懂得在线观看| 亚洲欧美日韩国产一区| 成人性生交大片免费看视频直播 | 日韩欧美在线免费观看视频| 国产午夜亚洲精品一级在线| 亚洲精品中文字| avove在线播放| 日韩成人一区二区三区在线观看| 不卡一区二区三区四区五区| 777电影在线观看| 亚洲国产成人精品视频| 99九九99九九九99九他书对| 日日狠狠久久偷偷综合色| 久久资源免费视频| 日韩电影在线观看一区二区| 国产福利一区二区三区视频在线| 日韩精品一区二区三区色偷偷| 9999在线视频| 日韩片之四级片| 欧美 日韩 国产 成人 在线观看| 欧美日韩精品| 成人h视频在线| 国产私人尤物无码不卡| 婷婷一区二区三区| 中文字幕一二三区| 99国产精品一区二区| 91av视频在线观看| 韩国av在线免费观看| 亚洲欧美日韩国产成人精品影院 | 99久久久久久| 久久福利一区二区| 国产精品亚洲欧美一级在线| 中文精品99久久国产香蕉| 国产又黄又猛又粗又爽| 成人黄色综合网站| 免费视频爱爱太爽了| 人人爱人人干婷婷丁香亚洲| 精品久久久av| 97精品人妻一区二区三区| 久久久久久久久久久黄色| 鲁一鲁一鲁一鲁一澡| 国产精品久av福利在线观看| 欧美黄色小视频| 亚洲国产精品久久久久爰性色| 亚洲美女区一区| 久久久九九九热| 午夜精品毛片| 91亚洲精品一区| 呦呦在线视频| 欧美成人性福生活免费看| 男女羞羞免费视频| 国产福利不卡视频| 欧美视频在线第一页| 91九色鹿精品国产综合久久香蕉| 欧美黑人巨大xxx极品| 成人免费视频国产免费麻豆| 亚洲成人一区在线| 国产在线观看无码免费视频| 新狼窝色av性久久久久久| 日本一区免费| 成人在线免费av| 久久在线免费观看视频| 国产丰满美女做爰| 亚洲成av人**亚洲成av**| 丰满大乳奶做爰ⅹxx视频| 国产欧美精品久久| 色999日韩自偷自拍美女| 另类一区二区| 欧美精品做受xxx性少妇| 日韩永久免费视频| 色拍拍在线精品视频8848| 国产精品成人无码免费| 精品一区二区影视| 久久这里只有精品8| 日韩深夜影院| 国产精品丝袜视频| 尤物视频在线看| 亚洲精选中文字幕| 一区二区精品视频在线观看| 亚洲精品欧美二区三区中文字幕| 欧美色图校园春色| 国产欧美午夜| 中国人体摄影一区二区三区| 91亚洲无吗| 国产精品av电影| 午夜影院免费在线| 亚洲欧洲成视频免费观看| 99久久精品国产成人一区二区| 亚洲超丰满肉感bbw| 天天舔天天操天天干| 国产剧情一区二区三区| 久久精品免费一区二区| 性xxxx欧美老肥妇牲乱| 精品视频第一区| 国产亚洲欧美日韩精品一区二区三区 | 亚洲精品男同| 亚洲免费视频一区| 大桥未久女教师av一区二区| 国产精品久久久久久久av电影 | 奇米成人av国产一区二区三区| 欧美高清视频| 亚洲男人第一av网站| 国产片在线播放| 欧美在线一二三四区| 国产在线观看你懂的| 欧美激情在线一区二区三区| 美女伦理水蜜桃4| 久久国产精品无码网站| 毛片在线视频播放| 99精品国产一区二区三区| 久久这里精品国产99丫e6| 蜜桃在线一区| 成人午夜在线观看| 在线国产成人影院| 7777精品视频| 欧美wwww| 久久久精品一区二区| 国产三区四区在线观看| 亚洲成人黄色在线| 国产美女三级无套内谢| 欧美视频一区二区三区| 亚洲精品www久久久久久| 亚洲人吸女人奶水| 91禁男男在线观看| 久久精品人人做人人综合| 97人妻精品一区二区三区免费| 激情六月婷婷久久| 天天色综合天天色| 国产一区二区三区的电影 | 精品一区二区三区免费看| 国产精品高潮呻吟久久av野狼| 亚洲精华液一区二区三区| 欧美大片在线看| 2021国产在线| 久久天天躁狠狠躁老女人| 嫩草香蕉在线91一二三区| 中文字幕日韩av电影| 自拍视频在线免费观看| 亚洲人成在线观看| 久久精品a一级国产免视看成人| 日韩av最新在线| 午夜在线视频观看| 亚洲精品福利在线观看| 污污视频在线免费看| 亚洲第一页自拍| 手机av免费在线观看| 精品sm捆绑视频| 亚洲 欧美 精品| 日韩精品在线观看一区二区| 手机亚洲第一页| 亚洲视频免费一区| 99se视频在线观看| 一区二区成人精品| 日本视频在线播放| 久久亚洲影音av资源网| 18videosex性欧美麻豆| 欧美日韩电影在线观看| h片在线观看视频免费| 国外成人在线视频| 人人草在线视频| 日本成人激情视频| 久久电影天堂| 97国产超碰| 成人自拍在线| 久久久久久国产精品免费免费| 精品一区毛片| 亚洲午夜精品国产| 欧美精品国产一区二区| 免费av手机在线观看| 天堂蜜桃91精品| 久久久久久久久久一区| 国产成人精品1024| 免费a级黄色片| 国产精品视频免费看| 2018天天弄| 欧美性黄网官网| 夜夜狠狠擅视频| 精品久久国产97色综合| 黄色在线小视频| 久久久精品一区二区| 国产黄大片在线观看| 国产精品久久久久7777婷婷| 麻豆国产一区二区三区四区| 久久久久久国产精品一区 | 国产精品网站在线播放| 日本一级二级视频| 欧美性猛交xxxx免费看久久久| 一区二区视频免费观看| 欧美va在线播放| 波多野结衣一区二区| 欧美激情视频一区二区| 日韩三区免费| 国产精品二区在线观看| 精品国产一区二区三区四区| 成年丰满熟妇午夜免费视频| 视频一区国产视频| 深夜视频在线观看| 国产嫩草影院久久久久| 日本三级免费看| 欧美日韩精品综合在线| 日本加勒比一区| 久久精品国产久精国产一老狼| 在线观看的黄色| 99久热re在线精品视频| 日韩高清欧美| 亚洲色欲综合一区二区三区| 福利一区二区在线| 蜜桃av免费看| 午夜久久电影网| 国产欧美一级片| 中文字幕日韩在线观看| 擼擼色在线看观看免费| 99久久自偷自偷国产精品不卡| 久久高清精品| 中文字幕在线观看第三页| 成人av网站在线观看免费| 欧美日韩午夜视频| 欧美在线不卡一区| 亚洲色图狠狠干| 欧美大片在线影院| 日韩欧美中文字幕一区二区三区| 色噜噜狠狠色综合网| 国产精品一卡| 一起草在线视频| 亚洲综合一二三区| 国产视频第一页| www.久久久久| 久久精品97| 亚洲精品一区二| 老鸭窝一区二区久久精品| 国产精品免费无码| 日韩欧美在线一区| 天堂中文在线8| 欧洲亚洲免费在线| 伦理一区二区| 免费 成 人 黄 色| av在线不卡电影| 成人免费区一区二区三区| 精品电影一区二区三区 | 婷婷另类小说| 超碰成人在线播放| 国产精品乱人伦一区二区| 自拍偷拍精品视频| 在线性视频日韩欧美| а√天堂资源国产精品| 日产中文字幕在线精品一区| 石原莉奈在线亚洲三区| 一级黄色片大全| 欧美亚洲一区三区| 日本在线看片免费人成视1000| 国产在线播放91| 久久精品欧美一区| 免费高清视频在线观看| 18成人在线观看| www.com在线观看| 久久全国免费视频| 日韩高清三区| 激情五月亚洲色图| 国产精品免费视频网站| 91在线观看喷潮| 欧美日韩999| 国产精品欧美大片| 人妻有码中文字幕| 国产精品乱码人人做人人爱| 国产精品自偷自拍| 久久久久女教师免费一区| 天堂综合网久久| 国产理论在线播放| 亚洲欧美电影一区二区| 殴美一级特黄aaaaaa| 浅井舞香一区二区| 91九色精品| 97精品人妻一区二区三区蜜桃| 色先锋久久av资源部| 在线免费观看黄色| 99re视频在线播放| 亚洲男女自偷自拍| 视频国产一区二区| 亚洲电影在线看| 日韩中文视频| 99国产精品白浆在线观看免费| 91蝌蚪porny九色| 国产伦精品一区二区三区视频痴汉| 欧美精品video| 精品欧美久久| 99久久久无码国产精品性波多| 日韩欧美综合在线视频| 国产盗摄在线观看| 狼狼综合久久久久综合网| 精品在线你懂的| 亚洲影院在线播放| 欧美日韩不卡合集视频| 欧美亚洲精品在线| 成年人小视频在线观看| 欧美性xxxxxx少妇|