精品欧美一区二区三区在线观看 _久久久久国色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ù)棧公眾號

www.精品av.com| 亚洲综合一区二区精品导航| 国产999在线| 中国美女黄色一级片| 欧美一级片网址| 天天影视色香欲综合网老头| 亚洲成人在线视频网站| 国内精品国产成人国产三级| 国产日韩亚洲欧美精品| 日韩一区二区福利| 中文字幕精品视频在线| 亚洲免费资源| 欧美日韩中文字幕在线| 中国成人在线视频| 视频国产在线观看| 国产在线麻豆精品观看| 欧洲成人午夜免费大片| 国产成人无码aa精品一区| 一区二区小说| 精品国产1区2区3区| 在线黄色免费观看| 色多多在线观看| 亚洲综合在线第一页| 亚洲欧洲日本国产| 嫩草研究院在线| 成人精品鲁一区一区二区| 国产一区深夜福利| 少妇久久久久久久| 999在线观看精品免费不卡网站| 视频直播国产精品| 给我免费观看片在线电影的| 日韩亚洲精品在线观看| 欧美在线一二三四区| 精品视频免费在线播放| 在线中文字幕第一页| 国产精品久久三区| 视频一区国产精品| 久久久久久久久亚洲精品| gogo大胆日本视频一区| 国产精品久久精品国产| 精品国产伦一区二区三| 激情综合网av| 成人免费视频网址| 亚洲最大成人av| 青青草国产成人99久久| 国产成人精品国内自产拍免费看| 91蜜桃视频在线观看| 亚洲高清电影| 韩国精品美女www爽爽爽视频| 欧美日韩精品在线观看视频| 综合五月婷婷| 久热在线中文字幕色999舞| 99成人在线观看| 91欧美在线| 久久久精品国产网站| 午夜激情福利电影| 一区二区三区四区日韩| 九九视频直播综合网| 免费在线观看av网址| 国产精品激情| 性欧美亚洲xxxx乳在线观看| 久久伊人成人网| 一道本一区二区| 日韩av电影手机在线| 日本高清不卡码| 日日夜夜免费精品视频| 国产精品欧美风情| 国产乱淫av片免费| 粉嫩嫩av羞羞动漫久久久| 岛国视频一区免费观看| 天天干天天做天天操| 久久影院午夜论| 日韩欧美亚洲日产国产| 欧美一级二级三级区| 亚洲综合在线五月| 国产成人久久婷婷精品流白浆| 最新日韩三级| 91精品国产综合久久香蕉的特点| 少妇伦子伦精品无吗| 婷婷成人在线| 色久欧美在线视频观看| 久久久久久久蜜桃| 蜜桃伊人久久| 亚洲aa中文字幕| 台湾av在线二三区观看| 国产精品区一区二区三区| 日韩久久久久久久久久久久| 欧美人与性动交xxⅹxx| 91精品国产一区二区三区香蕉| 中国特级黄色大片| 操欧美老女人| 欧美黑人狂野猛交老妇| 无码人妻一区二区三区线| 久久99热这里只有精品| 国偷自产av一区二区三区小尤奈| 东凛在线观看| 亚洲国产欧美在线| 视色视频在线观看| 欧美aaaaa级| 俺去了亚洲欧美日韩| 亚洲天堂av片| 国产精品1区二区.| 手机看片福利永久国产日韩| 中文在线字幕免费观看| 欧美亚洲综合色| 一级全黄裸体片| 日韩欧美精品综合| 欧美亚洲另类激情另类| 99re只有精品| 亚洲国产精品黑人久久久| 男人添女荫道口图片| 日韩在线你懂得| 亚洲天堂av电影| 日本少妇bbwbbw精品| 国产主播一区二区三区| 日韩欧美国产二区| 欧美日韩国产观看视频| 日韩一级成人av| 久久爱一区二区| 日韩黄色免费网站| 麻豆精品蜜桃一区二区三区| 日本理论片午伦夜理片在线观看| 欧美另类videos死尸| 日本激情小视频| 亚洲美女黄网| 99久久自偷自偷国产精品不卡| 国产污视频在线| 黄色成人在线播放| 四虎成人免费视频| 中国精品18videos性欧美| 国产精品免费网站| 97视频在线观看网站| 色婷婷精品久久二区二区蜜臀av | 粉嫩久久99精品久久久久久夜| 污视频在线免费观看一区二区三区| 精精国产xxxx视频在线野外| 日韩欧美一二三四区| caoporn91| 精品综合久久久久久8888| 五月天婷亚洲天综合网鲁鲁鲁| 精精国产xxx在线视频app| 亚洲黄色免费三级| 日本中文字幕网| av电影在线观看一区| 人人妻人人做人人爽| 国产成人精品福利| 韩剧1988免费观看全集| 手机在线精品视频| 精品福利视频导航| 蜜臀av一区二区三区有限公司| 亚洲美女少妇无套啪啪呻吟| 好吊色欧美一区二区三区 | 男女性杂交内射妇女bbwxz| 一区二区日韩欧美| 国产精品v欧美精品v日韩| 爱看av在线| 亚洲黄色www| 中文字幕69页| 中文字幕欧美区| 中文字幕国产免费| 五月天综合网站| 99国产在线视频| ririsao久久精品一区| 亚洲精品国产精品国产自| 天天干天天干天天操| 久久久精品黄色| 九色porny自拍| 在线国产一区二区| 国产无套精品一区二区| 欧美aa视频| 久久精品人人做人人爽| 囯产精品一品二区三区| 舔着乳尖日韩一区| 国产综合精品久久久久成人av| 极品销魂美女一区二区三区| 丁香色欲久久久久久综合网| 女人抽搐喷水高潮国产精品| 国产精品美女av| 中国av在线播放| 亚洲精品视频中文字幕| 亚洲视频在线观看免费视频| 亚洲精品乱码久久久久久久久| 人妻换人妻a片爽麻豆| 久久三级福利| 欧美日韩一级在线| 日日狠狠久久偷偷综合色| 国产精品永久免费| 久草在线资源站资源站| 国产一区二区三区在线视频 | 成人永久免费视频| 日日碰狠狠躁久久躁婷婷| 永久亚洲成a人片777777| 欧美激情论坛| 亚洲成人影音| 国产精品视频网址| 华人av在线| 欧美成人精品在线观看| 免费福利在线观看| 日韩欧美亚洲国产另类 | 日韩一级高清毛片| 国产成人无码专区| 亚洲国产欧美另类丝袜| 日韩欧美在线视频播放| 337p粉嫩大胆噜噜噜噜噜91av| 亚洲第一天堂久久| 久久精品日产第一区二区 | 可以看av的网站久久看| 真实国产乱子伦对白视频| 日韩国产欧美一区二区| 久久久综合香蕉尹人综合网| 免费观看亚洲天堂| 国产欧美精品一区二区三区-老狼| av资源中文在线| 欧美精品做受xxx性少妇| 国产高清免费av在线| 亚洲精品456在线播放狼人| av小说天堂网| 欧美日韩国产精选| 精人妻无码一区二区三区| 午夜视频在线观看一区二区| 三上悠亚作品在线观看| 欧美国产1区2区| 人人妻人人藻人人爽欧美一区| 成人精品免费视频| 又大又长粗又爽又黄少妇视频| 精品制服美女久久| www.99r| 日本不卡在线视频| 最近免费中文字幕中文高清百度| 亚洲激情精品| 国产欧美日韩小视频| 欧美日韩亚洲一区| 中文字幕色呦呦| 欧美在线首页| 亚洲av综合色区| 一区二区在线| 成人毛片100部免费看| 羞羞答答成人影院www| 亚洲一区二区三区精品动漫| jvid福利在线一区二区| 亚洲草草视频| 色综合天天爱| 最新中文字幕久久| 亚洲最新色图| h无码动漫在线观看| 欧美视频在线观看| 欧美日韩福利在线| 99精品视频免费观看视频| 国产青青在线视频| 性感少妇一区| 午夜免费一区二区| 美女高潮久久久| 国产一区二区在线观看免费视频| 卡一卡二国产精品| 女人扒开双腿让男人捅| 丁香一区二区三区| 精品无码国产一区二区三区51安| 99riav一区二区三区| 精品夜夜澡人妻无码av| 久久天天做天天爱综合色| 欧美a在线播放| 亚洲嫩草精品久久| 日韩精品国产一区二区| 日韩欧美a级成人黄色| 日韩一级片中文字幕| 欧美绝品在线观看成人午夜影视| 国产免费叼嘿网站免费| 亚洲丁香婷深爱综合| 欧美理论在线观看| 日韩在线小视频| 黄色在线看片| 青青草99啪国产免费| 久久久久伊人| 国产精品三区在线| 精品日韩一区| 国产一级大片免费看| 亚洲一区激情| 91国内在线播放| av在线这里只有精品| 国产精品www爽爽爽| 亚洲综合激情网| 日韩 国产 欧美| 欧美一三区三区四区免费在线看| 日韩中文字幕观看| 少妇av一区二区三区| 懂色av一区| 国产精品视频免费在线| 精品人人人人| 一道精品一区二区三区| 亚洲精品韩国| 日本国产一级片| 久久久一区二区三区| 欧美色图一区二区| 欧美综合久久久| 蜜桃视频污在线观看| 永久免费看mv网站入口亚洲| 欧美78videosex性欧美| 国产精品久久久久久久久久ktv| 日韩欧美中文字幕在线视频 | 性色av蜜臀av色欲av| 1区2区3区精品视频| 人人干人人干人人干| 91精品国产91久久综合桃花 | 日韩精品一区二区三区不卡| 国产在线一区二区综合免费视频| 中文字幕一区二区人妻在线不卡| 亚洲精品视频自拍| 中文字幕一区二区三区免费看 | 亚洲在线视频福利| 青青草原综合久久大伊人精品| 久久国产精品网| 国产乱对白刺激视频不卡| 天堂在线中文视频| 欧美日韩一区二区在线播放| 丰满肉肉bbwwbbww| 不卡毛片在线看| 欧美视频在线视频精品| 欧美性xxxx69| 亚洲欧洲日本mm| 国产免费无码一区二区| 亚洲欧美一区二区在线观看| 亚洲精品国产无码| 亚洲精品视频在线播放| 黄色在线观看www| 国产精品区二区三区日本| 亚洲一区二区三区| 手机在线国产视频| 国产精品国产三级国产aⅴ入口| 男人天堂视频在线| 亚洲色图50p| 国产 日韩 欧美一区| 欧美日韩国产精品一区二区| 国产亚洲在线观看| 久久久国产精品无码| 偷拍与自拍一区| 国产小视频免费观看| 国语自产精品视频在线看| 丁香综合av| 欧美大片在线播放| av一区二区三区在线| www..com国产| 亚洲欧美一区二区三区情侣bbw| 香蕉伊大人中文在线观看| 久久大香伊蕉在人线观看热2| 99精品国产在热久久| 97香蕉碰碰人妻国产欧美 | 97视频人免费观看| 红杏aⅴ成人免费视频| 蜜桃传媒一区二区三区| 91亚洲永久精品| 台湾佬中文在线| 中文日韩在线视频| 国产精品久久久久久久久久久久久久久| 一区二区三区国| 国产成人精品三级| 国产乡下妇女做爰| 日韩精品在线观| 五月激情久久| 懂色av一区二区三区四区五区| 国产精品一级片| 日韩精品视频免费看| 亚洲理论在线a中文字幕| 成人在线不卡| 永久免费看av| 99热这里都是精品| 欧美日韩在线视频播放| 久久香蕉频线观| 国产精品宾馆| 国产精品乱码久久久久| 亚洲欧洲国产专区| 国产91免费看| 国产精品对白刺激| 永久亚洲成a人片777777| 熟女丰满老熟女熟妇| 欧美吻胸吃奶大尺度电影| 1区2区在线观看| 日本高清不卡一区二区三| 经典三级在线一区| 青青国产在线观看| 日韩在线视频中文字幕| 国产精品白丝av嫩草影院| 免费看a级黄色片| 一区二区三区91| 成人在线观看黄色| 爱情岛论坛亚洲入口| 老司机精品视频网站| 国产精品久久久久久久精| 精品五月天久久| 成人97精品毛片免费看| 丝袜老师办公室里做好紧好爽| 国产精品久久福利| 日本加勒比一区| 成人国产亚洲精品a区天堂华泰| 亚洲伦伦在线| 精品国产视频在线观看| 亚洲美女性生活视频| 亚洲成人五区| 亚洲污视频在线观看| 黄网站色欧美视频| 91福利国产在线观看菠萝蜜|