HarmonyOS鸿蒙Next中字节数组生成码图不能被闸机识别的问题

HarmonyOS鸿蒙Next中字节数组生成码图不能被闸机识别的问题

问题现象

码图生成接口generateBarcode.createBarcode(contentBuffer, options),生成的二维码,不能通过机器刷码验证,解析出来的数据格式不满足闸机要求。用h5的jquery.qrcode.min.js工具生成的二维码,机器刷码正常识别。对比解码的数据有不同,在头部多了“703”数据。

代码信息

showQrCode(content:string){
  content="4a02013202100008295454200306000000000000975073dd00b401c7bd9c9b01f4057ed1e3177ff8aad59ad4b90f355384b46c2a709fc8b1aa4fef0832a088adeb46bca0787ea7f0b183ce31bf233292f4ec2037cd242e2724e15dfc24fd3c42c60200a335da5d55103530303331303131303032363737323003fd58699f243f9eb96f3f2460136064f8d6bdb3e955475a5ee6bbca72a6789b2b03e86a2d09893f1b5aaebbdcd928b5793a83992ce050a552066a101ecd3e64b1feed571ae26ea5255ac7b23ccbccaf7fb511d378d9d7b976f50a190e5916c9f5652d5561bc9476f5c3b66a2bb8ef0c100300000000000040030001005d565224f335fa066398ce872afe8cbfcf1a555db699a74fde7e271e6867ea66c08ce9cb7aa90124f1610ffbf14e8dcbc1bf043b29695614a6ba8f549dfe8af6"

  LogUtil.debug("wwwwww", '[generateBarcode]',`code长度: ${content.length}`);
  
  // 将包含十六进制字符的字符串转换成字节数组ArrayBuffer
  const contentBuffer: ArrayBuffer = buffer.from(content, 'hex').buffer;
  LogUtil.debug("wwwwww", '[generateBarcode]',`contentBuffer长度: ${contentBuffer.byteLength}`);
  LogUtil.debug("wwwwww", '[generateBarcode]',`contentBuffer内容: ${new Uint8Array(contentBuffer)}`);
  
  let sizePx = this.getUIContext().vp2px(this.qrCodeSize)
  LogUtil.debug("wwwwww", '[generateBarcode]',`码尺寸px: ${sizePx}`);

  // 以QR码为例,码图生成参数
  let options: generateBarcode.CreateOptions = {
    scanType: scanCore.ScanType.QR_CODE,
    height: sizePx,
    width: sizePx,
    margin: 2,
    level: generateBarcode.ErrorCorrectionLevel.LEVEL_M,
    backgroundColor: 0xFFFFFF,
    pixelMapColor: 0x000000,
  };
  try {
    // 码图生成接口,成功返回PixelMap格式图片
    generateBarcode.createBarcode(contentBuffer, options).then((pixelMap: image.PixelMap) => {
      this.qrCodePixelMap = pixelMap;

    }).catch((err: BusinessError) => {
      LogUtil.debug("wwwwww", '[generateBarcode]',
        `Failed to get PixelMap by promise with options. Code: ${err.code}, message: ${err.message}`);
    });
  } catch (err) {
    LogUtil.debug("wwwwww", '[generateBarcode]',
      `Failed to createBarcode by promise with options. Code: ${err.code}, message: ${err.message}`);
  }
}

问题日志

用h5的jquery.qrcode.min.js工具生成的二维码,正常识别,(码的大小、纠错等级背景色等参数与鸿蒙端一致)

用zxing解析工具(https://zxing.org/w/decode)解析的二维码的数据结构如下图

版本信息

手机系统版本:5.1.0、
DevEco Studio版本:DevEco Studio 5.1.1 Release

Build #DS-233.14475.28.36.511820

Build Version: 5.1.1.820, built on June 28, 2025

Runtime version: 17.0.12+1-b1087.25 amd64

VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.

Windows 10.0

GC: G1 Young Generation, G1 Old Generation

Memory: 1024M

Cores: 16

Registry:

idea.plugins.compatible.build=IC-233.14475.28

Non-Bundled Plugins:

com.bangcle.HarmonyObfuscator (ver2.5_HMNR_rel_250731.1)

Api语言版本:HarmonyOS 5.1.1 Release SDK, inclusion of OpenHarmony SDK Ohos_sdk_public 5.1.1.202 (API Version 19 Release) as is.

三方库版本:

// 导入码图生成需要的图片模块、错误码模块
import { scanCore, generateBarcode } from '@kit.ScanKit';

复现步骤


更多关于HarmonyOS鸿蒙Next中字节数组生成码图不能被闸机识别的问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

15 回复

【解决方案】

开发者您好,上述问题是5.x版本中码图生成接口的已知问题,已在6.0.0版本修复。需要您升级到6.0.0及以上版本进行使用。

更多关于HarmonyOS鸿蒙Next中字节数组生成码图不能被闸机识别的问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


开发者您好,可以参考该文档中的示例代码尝试是否可以解决问题:

如何解决生成的二维码无法使用的问题

我这边建议先改这里:不要直接把 buffer.from(content, ‘hex’).buffer 传给 createBarcode。generateBarcode 的 ArrayBuffer 重载要求传入“码内容字节数组”,而 Buffer.buffer 是底层 ArrayBuffer,某些实现里它不一定只覆盖当前 Buffer 视图的有效区间;如果把多余前缀/尾部一起编码进去,闸机按交通码协议解码时就会看到额外头部,比如您说的“703”。

可以先这样构造精确长度的 ArrayBuffer:

import { buffer } from '@kit.ArkTS';

function hexToExactArrayBuffer(hex: string): ArrayBuffer {
  if (hex.length % 2 !== 0) {
    throw new Error('hex length must be even');
  }
  const src = buffer.from(hex, 'hex');
  const bytes = new Uint8Array(src.length);
  for (let i = 0; i < src.length; i++) {
    bytes[i] = src[i];
  }
  return bytes.buffer;
}

const contentBuffer = hexToExactArrayBuffer(content);
console.info('expect=' + content.length / 2 + ', actual=' + contentBuffer.byteLength);
await generateBarcode.createBarcode(contentBuffer, options);

再做两步对比:1)把 contentBuffer 转回 hex,确认首字节就是 4a、长度等于 content.length / 2;2)用同一个解码工具分别解 H5 和 ArkTS 生成图,比较原始字节而不是展示字符串。如果精确 ArrayBuffer 后 5.1.0 仍异常、6.0.0 正常,那就很像 5.1 Scan Kit 字节数组生成链路的兼容问题,建议带最小 demo、两张码图、解码后的原始 hex 和系统版本提交工单。

参考:

https://developer.huawei.com/consumer/cn/doc/harmonyos-references/scan-generatebarcode

找HarmonyOS工作还需要会Flutter技术的哦,有需要Flutter教程的可以学学大地老师的教程,很不错,B站免费学的哦:
https://www.bilibili.com/video/BV1S4411E7LY/?p=17

cke_866.png

谢谢大佬提供的思路,
先这样构造精确长度的 ArrayBuffer,把 contentBuffer 转回 hex,确认首字节就是 4a,生成的码,解析后最终还是有703。

升级到6.0吧。

通过字节数组生成的码图无法识别

问题现象

Scan Kit识别该码图内容显示内容为乱码,无法解析。

解决措施

通过字节数组生成码图,Scan Kit识别该码图内容显示内容为乱码,这种字节数组需要专门的解码器解析,例如地铁闸机。

https://developer.huawei.com/consumer/cn/doc/atomic-guides/atomic-scan-faq

如果在鸿蒙5.1异常的话,建议提交工单向官方反馈一下,可能与插件等有关,

用过zxing库,只能传string类型,满足不了我们的业务,我们需要将字节数组生成码图

Harmonyos版本5.1.0 异常

harmonyos版本6.0.0 正常

你是不是搞错了,已经是字符串了,直接转换成二维码就行了啊!

交通一卡通二维码,需要通过字节数组生成码图

你还是用第三方库zxing吧,这个是比较知名的通用库:https://ohpm.openharmony.cn/#/cn/detail/@ohos%2Fzxing

字节数组生成码图无法被闸机识别,通常是字节数据编码格式与闸机解码规则不匹配,或码图生成参数(QR版本、纠错级别、掩码)不符合标准。检查字节流是否按UTF-8/GBK正确转换,码图尺寸和对比度是否足够,避免使用非标准压缩或自定义协议。,

问题原因不是二维码参数,而是内容格式不一致

  • H5 的 jquery.qrcode.min.js 是把 content 这个十六进制字符串直接当作文本内容生成二维码;
  • 鸿蒙代码里却先用 buffer.from(content, 'hex') 把它转成了原始字节数组,再传给 createBarcode

闸机期望的数据是“十六进制 ASCII 字符串”,而你传入的是这些十六进制字符对应的二进制值,所以解析结果不同。头上多出的“703”很可能是二进制数据被解码时产生的字符。

解决:直接传 content 字符串,不要转 ArrayBuffer。

修改代码:

generateBarcode.createBarcode(content, options).then(...)

即去掉 contentBuffer 的构造,把 content 作为第一个参数传入。这样生成的二维码内容和 H5 版本一致,闸机即可正常识别。

回到顶部