HarmonyOS鸿蒙Next中Flutter SDK如何实现扫码功能

HarmonyOS鸿蒙Next中Flutter SDK如何实现扫码功能

3 回复

在开发App时候,扫码功能往往是最基本和最常用的功能,本文将系统介绍如何用鸿蒙Flutter SDK完成扫码功能的开发,包括扫码结果处理、扫码框设计、闪光灯控制以及读取相册等。

引入第三方库

Flutter要实现扫码功能,可以使用第三方库mobile_scanner,不过不要直接使用pub.dev的库,要使用做过鸿蒙适配的第三方库,然后在pubspec.yml引用该库即可。

cke_936.png

扫码界面

可以通过StatefulWidget实现扫码界面,在界面中间显示一个扫码框,在扫码框下方显示一个闪光灯图标,可以开启或者关闭闪光灯,标题栏右边显示相册文字,可以识别照片中的二维码,最终的效果如下:

cke_1624.png

扫码组件代码

可的定义一个MobileScannerController变量,并在initState对其进行初始化。

_scannerController = MobileScannerController(
      detectionSpeed: DetectionSpeed.normal,
      facing: CameraFacing.back,  // 使用后置摄像头
      torchEnabled: _isFlashOn,   // 支持闪光灯
    );

然后在build方法中使用MobileScanner组件,并引入上面的_scannerController

MobileScanner(
            controller: _scannerController,
            onDetect: (capture) {
              if (_isScanning && capture.barcodes.isNotEmpty) {
                _handleScanResult(capture.barcodes);
              }
            },
          ),

处理扫码获得的结果,当识别到多个码时,可以优先返回符合某一个规则的的码,比如https开头的码。

void _handleScanResult(List<Barcode>? barcodes) {
    if (barcodes!.isEmpty) {
      return;
    }
    for (Barcode barcode in barcodes) {
      if (barcode.rawValue == null) {
        continue;
      }
      if (barcode.rawValue!.startsWith("https")) {
        _goBack(barcode);
        return;
      }
    }
    _goBack(barcodes.first);
  }

扫码框代码

扫码框为正方形,需要显示在界面正中间,扫码框的宽高是手机屏幕宽的三分之二。

final screenSize = MediaQuery.of(context).size; // 手机屏幕尺寸
final scanBoxSize = screenSize.width * 2 / 3; // 扫码框的宽高
Positioned(
            left: (screenSize.width - scanBoxSize) / 2,
            top: (screenSize.height - scanBoxSize) / 4,
            child: SizedBox(
              width: scanBoxSize,
              height: scanBoxSize,
              child: Stack(
                children: [
                  // 扫码框边框
                  CustomPaint(
                    painter: ScannerBorderPainter(),
                    size: Size(scanBoxSize, scanBoxSize),
                  ),
                ],
              ),
            ),
          ),

闪光灯代码

当闪光灯关闭时候,显示为闪光灯关闭的图标,当闪光灯打开时候,显示为闪关灯开启的图标,这个图标本质上是一个图标按钮IconButton,通过点击事件触发扫码_scannerController关闭或者开启闪光灯。

Positioned(
            // bottom: 80,
            // right: 50,
            left: (screenSize.width - 30) / 2,
            bottom: 80,
            child: IconButton(
              icon: Icon(
                _isFlashOn ? Icons.flashlight_on : Icons.flashlight_off,
                color: Colors.white,
                size: 30,
              ),
              onPressed: _toggleFlashlight,
            ),
          ),
Future<void> _toggleFlashlight() async {
    if (!_scannerController.value.isInitialized) return;
    setState(() {
      _isFlashOn = !_isFlashOn;
    });
    // print("torchState: ${_scannerController.value.torchState}");
    if (_scannerController.value.torchState != TorchState.unavailable) {
      await _scannerController.toggleTorch();
    }
  }

相册代码

除了通过扫描识别二维码外,有时还需要识别图片中二维码,幸运的是,mobile_scanner库支持识别图片中的二维码,相册按钮显示在标题栏的右边,点击相册按钮就可以打开相册,然后从相册选择要识别二维码的图片。值得一提的是,可以使用image_picker第三方库读取相册。

appBar: AppBar(
        title: const Text("扫码"),
        centerTitle: true,
        actions: [
          TextButton(
              onPressed: () {
                _pickImageFromGallery();
              },
              child: const Text(
                '相册',
                style: TextStyle(
                    color: Colors.white,
                    fontWeight: FontWeight.bold,
                    fontSize: Global.textSizeBase),
              ))
        ],
      ),
Future<void> _pickImageFromGallery() async {
    final ImagePicker picker = ImagePicker();
    final XFile? image = await picker.pickImage(source: ImageSource.gallery);

    final BarcodeCapture? result = await _scannerController.analyzeImage(
      File(image.path).path,
    );

    if (result?.barcodes.isNotEmpty == true) {
      _handleScanResult(result?.barcodes);
    } else {
      ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text("未识别到二维码")),
      );
    }
  }

到此,扫码功能就基本实现,扫码的结果可以返回给调用扫码界面的代码进一步处理。

更多关于HarmonyOS鸿蒙Next中Flutter SDK如何实现扫码功能的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在HarmonyOS鸿蒙Next中实现Flutter扫码功能

在HarmonyOS鸿蒙Next中实现Flutter扫码功能,需使用华为提供的鸿蒙原生能力。Flutter通过Platform Channel调用鸿蒙侧实现的扫码模块。鸿蒙侧使用@ohos.multimedia.image库处理图像,@ohos.security.huks进行安全校验。

具体步骤

  1. 鸿蒙侧封装扫码服务,提供图像捕获与二维码解析;
  2. Flutter侧通过MethodChannel调用该服务
  3. 返回解析结果至Flutter界面。

注意:需在鸿蒙模块的build-profile.json5中声明相机权限。

在HarmonyOS Next中使用Flutter SDK实现扫码功能,目前主要有两种技术路径:

1. 使用HarmonyOS原生能力桥接 这是当前推荐的方式,通过Flutter插件调用HarmonyOS的扫码原生接口:

  • 创建Flutter Plugin,在Android/iOS端使用原有扫码方案
  • 在HarmonyOS端实现ScanKit的调用,通过FFIPlatform Channel与Dart层通信
  • 需要分别实现Zxing(Android)和AVFoundation(iOS)的扫码适配

2. 纯Dart实现方案 使用纯Dart的扫码库(如mobile_scanner),但需要注意:

  • 相机权限需要适配HarmonyOS的权限模型
  • 相机帧获取可能需要通过HarmonyOS相机服务转接
  • 性能可能低于原生方案

关键实现步骤:

  1. 配置HarmonyOS相机权限:在module.json5中添加ohos.permission.CAMERA权限
  2. 封装扫码服务:通过@ohos.zxing库实现二维码解析
  3. 建立通信通道:使用MethodChannel传递扫码结果到Flutter层
  4. 界面集成:在Flutter侧使用CameraPreview组件显示取景框

注意事项:

  • HarmonyOS Next的相机API与Android有差异,需要重新适配
  • 扫码性能优化需考虑HarmonyOS的图形渲染机制
  • 建议优先使用华为提供的ScanKit服务,识别率更高

目前官方尚未提供完整的Flutter扫码插件,需要开发者自行封装HarmonyOS原生能力。建议关注HarmonyOS开发者社区的更新,后续可能会有官方支持的扫码插件发布。

回到顶部