三方库仓库: https://atomgit.com/oh-flutter/haptic_kit

OHOS 适配分支: feat/ohos_haptic_kit_2.2.0

本文锁定版本: b6554f75bbd94b30ab5d34cc55d270570dfe8bd5

完整 Demo: haptic_kit/example(受测提交)

一、当前真机结果

在这里插入图片描述

图 1:签名 HAP 已在 CHZ-AL00 / HarmonyOS 7.0.0.105 上启动,页面包含语义触感、波形、预设和取消入口。截图只能证明页面启动,不能证明手感。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

检查项当前结论
固定提交依赖通过,必须使用适配分支提交,默认 main 无 OHOS 代码
静态检查与构建最终提交通过
自动化63 项 Dart 契约测试及最终 7 项 ArkTS 取消竞态回归通过
真机启动通过
物理振感待人工确认,属于发布阻塞项

二、选用哪一层 API

haptic_kit 同时提供低层振动和带触感的 Widget。我的使用原则是:离散 UI 操作用 Haptics,持续或可取消振动用 Vibration,复杂节奏用 HapticPattern,已有交互组件则优先使用库里的 HapticToggleHapticSlider 等封装。

API适合场景关键边界
Haptics.impact()按钮按下、卡片吸附短促语义反馈
Haptics.notification()成功、警告、错误不替代视觉提示
Haptics.selection()滑块刻度、选择器高频调用要节制
Vibration.vibrate()明确时长的一次振动duration 必须大于 0
Vibration.vibrateWaveform()自定义时序或重复提醒重复播放必须提供取消入口
HapticCapabilities.query()运行时能力判断查询成功不等于主观触感验收

三、环境、依赖和权限

本文使用 Flutter OH 3.41.10-ohos-1.0.1、Dart 3.11.5、DevEco Studio 26.0.0 Release、HarmonyOS API 26 和 CHZ-AL00。3.44.9+ohos-0.0.1-canary1 是预览标签,不是本次实测环境。

仓库默认 main 仍停在上游 602b6c5...,没有 OHOS 目录。只写 Git URL 会取错代码,必须固定适配提交:

dependencies:
  haptic_kit:
    git:
      url: https://atomgit.com/oh-flutter/haptic_kit.git
      ref: b6554f75bbd94b30ab5d34cc55d270570dfe8bd5
flutter pub get

插件 HAR 声明 ohos.permission.VIBRATE。构建最终 HAP 后应核对权限合并;该权限无需业务页面主动弹窗申请。

在这里插入图片描述

图 2:默认分支与 OHOS 适配分支不同,依赖不能省略 ref

四、先查能力,再选择反馈

import 'package:haptic_kit/haptic_kit.dart';

Future<void> playConfirmation() async {
  final HapticCapabilities capabilities =
      await HapticCapabilities.query();
  if (!capabilities.hasVibrator) return;

  if (capabilities.supportsImpactFeedback) {
    await Haptics.notification(HapticNotificationStyle.success);
  } else {
    await Vibration.vibrate(duration: const Duration(milliseconds: 80));
  }
}

能力查询用于选择路径,不能当作“用户一定能感知到”的证明。应用还应尊重自己的触感开关:

HapticSettings.enabled = userPreferences.hapticsEnabled;

关闭后所有播放调用成为无操作,但能力查询和 Vibration.cancel() 仍可执行。这样可以确保用户关闭触感时,不必在每个按钮前重复写判断。

五、单次、波形和取消

Future<void> playWarningPattern() async {
  try {
    await Vibration.vibrateWaveform(
      timings: const <Duration>[
        Duration.zero,
        Duration(milliseconds: 100),
        Duration(milliseconds: 80),
        Duration(milliseconds: 180),
      ],
      amplitudes: const <int>[0, 100, 0, 220],
      repeat: -1,
    );
  } on VibrationException catch (error) {
    debugPrint('haptic failed: $error');
  }
}

Future<void> stopWarningPattern() => Vibration.cancel();

参数校验在 Dart 层完成:时长必须为正,幅度为 1 到 255,波形的 timings/amplitudes 数量要匹配。重复播放时,页面必须提供停止按钮,并在离开业务流程前 await Vibration.cancel()

取消还有一个不容易看出的竞态:能力查询可能还没返回,用户已经点击停止。最终提交用 generation 隔离旧任务,保证晚到查询不会在取消后重新启动振动。

在这里插入图片描述

图 3:能力查询、预置效果、普通振动降级和取消代次保护。

六、一个可复用的按钮流程

class ConfirmButton extends StatefulWidget {
  const ConfirmButton({super.key, required this.onConfirmed});
  final Future<void> Function() onConfirmed;

  
  State<ConfirmButton> createState() => _ConfirmButtonState();
}

class _ConfirmButtonState extends State<ConfirmButton> {
  bool _busy = false;
  String? _error;

  Future<void> _confirm() async {
    if (_busy) return;
    setState(() {
      _busy = true;
      _error = null;
    });
    try {
      await widget.onConfirmed();
      await Haptics.notification(HapticNotificationStyle.success);
    } on VibrationException catch (error) {
      if (mounted) setState(() => _error = error.message);
    } finally {
      if (mounted) setState(() => _busy = false);
    }
  }

  
  Widget build(BuildContext context) => Column(
    children: <Widget>[
      FilledButton(onPressed: _busy ? null : _confirm, child: const Text('确认')),
      if (_error != null) Text(_error!),
    ],
  );
}

业务操作成功后再发 success 触感,不能按钮一按就先震“成功”。触感始终是补充反馈,错误、成功和可访问性状态仍需要视觉或语音表达。

七、检查和人工验收

在这里插入图片描述

图 4:Dart 契约和最终 ArkTS 取消竞态回归的实际统计。

在这里插入图片描述

图 5:最终提交的 HAP 与依赖锁定证据。

在这里插入图片描述

图 6:当前已完成与待完成项;物理振感不能由截图替代。

人工验收至少要确认 light/medium/heavy 能否区分,success/warning/error 时序是否合理,单次时长、波形节奏、重复取消后是否立即停止,以及不支持高清触感时的普通振动降级。每一项都要由操作者实际感知并记录。

八、常见问题

Q1:依赖成功但 OHOS 上 MissingPlugin

  • 现象: pub get 正常,运行时插件未注册。
  • 原因: 依赖落到默认 main,该分支没有 OHOS 代码。
  • 解决方法: 固定 b6554f7... 并核对 resolved-ref
  • 验证结果: 适配提交 HAP 可构建并在真机启动。

Q2:取消后又出现一次振动

  • 现象: 点击 cancel 时能力查询仍在进行,稍后又开始播放。
  • 原因: 旧异步结果越过取消边界。
  • 解决方法: 使用包含 generation 修复的最终提交,不要锁定早期适配 SHA。
  • 验证结果: 7 项 ArkTS 回归覆盖取消和晚到能力结果。

Q3:prepare 返回 false 是失败吗

  • 现象: 调用 Haptics.prepare() 得到 false。
  • 原因: 某些平台没有可预热的生成器,false 表示无操作,不表示后续触感一定失败。
  • 解决方法: 把 prepare 当可选优化,实际播放按能力与异常决定。
  • 验证结果: 当前物理结果仍待人工确认,不能只用返回值下结论。

九、总结

使用 haptic_kit 时最重要的是选对 API 层、尊重用户开关、为重复波形提供取消,并固定包含取消竞态修复的适配提交。代码和 HAP 已具备复现条件,但本篇仍处于待发布状态,最后一步是完成真机物理振感验收。

十、参考链接

欢迎加入CPF-Flutter 鸿蒙社区:https://atomgit.com/CPF-Flutter

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐