关键词:Flutter、OpenHarmony、MethodChannel、权限配置、扫码、问题排查

摘要

这篇文章记录了我在一个 Flutter + OpenHarmony 项目中落地“扫一扫”功能的完整过程。
不仅包含功能实现思路,还重点复盘了两个典型问题:

  1. hvigor 构建失败:user_grant 权限缺少 reason / usedScene
  2. 页面输入交互异常:弹层无法交互,随后出现 TextEditingController disposed 崩溃

最终方案是:先打通 Flutter 侧流程并提供降级路径,再按 OpenHarmony 规范补齐权限,最后用“无 controller 输入”规避平台兼容问题。


一、需求与目标

项目首页已有“扫一扫”按钮,但没有实际行为。
目标是实现一个“可上线联调”的版本:

  1. 点击“扫一扫”进入扫码流程
  2. 支持扫码结果展示与复制
  3. 原生扫码能力未接入时也能可用(降级输入)
  4. 保证 OpenHarmony 构建通过、页面交互稳定

二、实现策略:先闭环,再增强

我采用的是渐进式实现,而不是一开始就把所有端能力做满:

  1. 先打通入口与页面流转(用户可操作)
  2. MethodChannel 预留原生扫码接口(后续可无缝补齐)
  3. 原生未接入时自动降级到手动输入(保障功能可用)
  4. 针对平台报错和交互问题逐个修复

这套策略的核心是:先确保业务流程可跑通,再处理平台细节与兼容性。


三、核心实现

1)首页接入扫一扫入口

在首页快捷功能区,把“扫一扫”按钮改为页面跳转:

  • 文件:lib/pages/home/home_page.dart
  • 行为:点击后 Navigator.pushScanPage
  _buildActionButton(
              label: '扫一扫',
              icon: Icons.qr_code_scanner,
              onPressed: () => Navigator.of(
                context,
              ).push(MaterialPageRoute(builder: (_) => const ScanPage())),
  ),

2)新增扫码页:统一处理扫码与降级

新增页面:

  • 文件:lib/pages/scan/scan_page.dart

页面能力包括:

  1. 调用 MethodChannel('app.scan/qr')scan 方法
  2. 拿到结果后展示在页面中
  3. 支持“一键复制结果”
  4. 如果抛出 MissingPluginException(原生未实现),自动进入手动输入流程
static const MethodChannel _scanChannel = MethodChannel('app.scan/qr');
......
Future<void> _startScan() async {
    if (_isScanning) {
      return;
    }

    setState(() {
      _isScanning = true;
    });

    try {
      final dynamic value = await _scanChannel.invokeMethod<dynamic>('scan');
      final String scanned = (value ?? '').toString().trim();

      if (!mounted) {
        return;
      }

      if (scanned.isEmpty) {
        _showMessage('未识别到有效内容');
      } else {
        setState(() {
          _result = scanned;
        });
      }
    } on MissingPluginException {
      if (mounted) {
        setState(() {
          _isScanning = false;
        });
      }
      await _fallbackManualScan();
      return;
    } on PlatformException catch (e) {
      if (!mounted) {
        return;
      }
      _showMessage('扫码失败: ${e.message ?? e.code}');
    } finally {
      if (mounted && _isScanning) {
        setState(() {
          _isScanning = false;
        });
      }
    }
  }

这样做的好处是:Flutter 侧功能完整,原生能力可后续增量接入。
!](https://i-blog.csdnimg.cn/direct/be688130fbd74f36b8e8b499f0fd9512.png)


四、关键问题复盘

问题 1:hvigor 构建失败(00303218 Configuration Error)

现象

构建报错指出:

  • The reason and usedScene attributes are mandatory for user_grant permissions.

根因

我最初只添加了:

  • ohos.permission.CAMERA

但 OpenHarmony 对 user_grant 权限要求更严格,必须同时提供:

  1. reason
  2. usedScene

修复

module.json5 中补齐完整结构:

{
  "name": "ohos.permission.CAMERA",
  "reason": "$string:camera_permission_reason",
  "usedScene": {
    "abilities": ["EntryAbility"],
    "when": "inuse"
  }
}

并在多语言资源中新增 camera_permission_reason

  • ohos/entry/src/main/resources/base/element/string.json
  • ohos/entry/src/main/resources/zh_CN/element/string.json
  • ohos/entry/src/main/resources/en_US/element/string.json

问题 2:手动输入弹窗出现后无法交互

现象

降级路径使用 AlertDialog + TextField,弹窗出现后“看起来卡死,无法交互”。

第一轮修复

将弹窗输入改为独立页面输入Navigator.push),规避弹层交互兼容问题。
在这里插入图片描述


问题 3:TextEditingController was used after being disposed

现象

改成独立页面后,又出现崩溃:

  • A TextEditingController was used after being disposed.

根因分析

在当前 Harmony 适配环境中,输入组件生命周期与 controller 回收时机存在兼容风险,导致 controller 在销毁后仍被引用。

最终修复

移除 TextEditingController,改为:

  1. TextField.onChanged 保存字符串状态
  2. 点击“确定”直接提交字符串

这是一个“降复杂度换稳定性”的方案,实测有效规避该类崩溃。


五、最终效果

当前版本已经达到“可用且稳定”的阶段:

  1. 首页可进入扫一扫流程
  2. 原生扫码接口已预留(MethodChannel)
  3. 未接原生时可用手动输入完成流程
  4. 扫码结果可展示、可复制
  5. OpenHarmony 权限配置规范,构建错误已修复
  6. 输入交互和 controller disposed 问题已解决

六、这次实践的经验总结

  1. 先闭环再完善:先让用户能用,再做端能力增强
  2. 读懂平台约束:OpenHarmony 权限不仅是 nameuser_grant 要求完整结构
  3. 遇到弹层问题先页面化:弹窗异常时,独立页面通常更稳
  4. 输入崩溃优先降复杂度:必要时不要执着 controller,onChanged 足够解决问题
  5. 每次改动都做最小验证:格式化 + 局部 analyze,快速发现回归

七、后续可继续优化

  1. 接入 OpenHarmony 原生摄像头扫码实现,打通 app.scan/qr
  2. 增加扫码类型识别(URL、纯文本、Wi-Fi、联系人等)
  3. 补充扫码历史记录与去重策略
  4. 完善权限拒绝时的引导与重试链路

结尾

如果你也在做 Flutter + OpenHarmony 适配,欢迎交流你遇到的权限或输入兼容问题。我可以再写一篇:如何把 MethodChannel 原生扫码能力完整接到 OHOS 侧(含端到端代码结构)。

示例地址,点击跳转到gitcode

欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐