Flutter 鸿蒙使用实战:用 audioplayers 三方库给应用加上音频播放与进度控制
Flutter 鸿蒙使用实战:用 audioplayers 三方库给应用加上音频播放与进度控制
Flutter 社区地址: https://atomgit.com/CPF-Flutter/flutter_flutter
github三方库地址:https://github.com/bluefireteam/audioplayers
pub地址:https://pub.dev/packages/audioplayers
鸿蒙适配版:https://atomgit.com/CPF-Flutter/flutter_audioplayers
示例工程地址:https://atomgit.com/weixin_52908342/audio_demo
库版本:audioplayers 6.5.1(CPF-Flutter 鸿蒙适配版,commit
b853cda)|验证环境:Flutter 鸿蒙 SDK 3.44.9(oh-3.44.9-dev)|DevEco Studio 26.0.0.821 | 设备:DevEco 模拟器 Pura X View | HarmonyOS 7.0.0.106(API 26)
应用里的提示音、语音播报、按键音效、短音频动效几乎离不开音频播放。audioplayers 是 Flutter 生态里月下载 70 万级的主流音频库,CPF-Flutter 社区已在 flutter_audioplayers monorepo 里完成鸿蒙适配(audioplayers_ohos 平台包)。本文介绍它在 OpenHarmony 上的引入方式、播放控制与事件流监听的全接口调用,以及在 DevEco 模拟器上播放资产音频的真实运行效果。



一、环境搭建
本章不重复展开,直接引用官方文档:Flutter OH 开发环境搭建指导。
完成后用 flutter doctor -v 验证,Flutter 与 HarmonyOS toolchain 两项均为 [√] 即可。本文实际使用版本:Flutter OH oh-3.44.9-dev(commit 77e0c8d13b)、DevEco Studio 26.0.0.821、HarmonyOS SDK API 26。

二、应用背景

2.1 当前的应用场景与痛点
- 语音提示类:扫码成功音、消息提示音、导航播报
- 媒体类:播放本地/网络音频、逐句跟读、有声书
- 游戏/互动类:按键音效、动效反馈音
- 儿童教育类:字母卡片发音、跟读评分
痛点:Flutter 官方 audioplayers 只覆盖 Android/iOS/Web/macOS/Linux/Windows 六端,鸿蒙侧此前需自己写 ArkTS 播放器——现在 CPF-Flutter 已提供 audioplayers_ohos 平台包,开箱即用。
2.2 为什么需要这个库
自己写鸿蒙播放器要处理 AVPlayer 状态机、prepare/start/stop 生命周期、seek 精度、事件回调桥接;audioplayers 的鸿蒙适配版由社区维护,API 与其他平台完全一致,业务代码零改动迁移。
2.3 解决什么问题
一句话总结:让 Flutter 应用在鸿蒙上以与 Android/iOS 完全相同的 API 播放、控制、监听音频。具体提供:
- 播放控制:
play/pause/resume/stop/seek - 音量调节:
setVolume - 五个事件流:状态 / 时长 / 进度 / 播放完成 / seek 完成
- 多来源:
AssetSource(资产)/UrlSource(网络)/DeviceFileSource(本地文件)
三、功能介绍
| 功能 | API | 说明 | 适用场景 |
|---|---|---|---|
| 播放资产 | play(AssetSource('audio/x.m4a')) | 播放打包进应用的音频 | 提示音、内置音效 |
| 播放网络 | play(UrlSource('https://...')) | 流式播放在线音频 | 在线音乐、播客 |
| 暂停/继续/停止 | pause() / resume() / stop() | 播放控制三件套 | 播放器 UI |
| 进度跳转 | seek(Duration) | 跳到指定位置,onSeekComplete 回调 | 进度条拖动 |
| 音量 | setVolume(0.0~1.0) | 0-1 浮点 | 音量滑条 |
| 状态流 | onPlayerStateChanged | playing/paused/stopped/completed | UI 状态联动 |
| 时长/进度流 | onDurationChanged / onPositionChanged | 毫秒级 Duration | 进度条实时刷新 |
| 完成事件 | onPlayerComplete | 单曲播完触发 | 自动连播/循环 |
四、使用方法
4.1 在应用中引入三方库(AtomGit 链接方式)
dependencies:
audioplayers:
git:
url: https://atomgit.com/CPF-Flutter/flutter_audioplayers.git
ref: b853cdafdef1549be31b478a954f6d8b36d314e6
path: packages/audioplayers
dependency_overrides: # 关键!锁 ohos 实现包与接口包到同一 commit
audioplayers_ohos:
git:
url: https://atomgit.com/CPF-Flutter/flutter_audioplayers.git
ref: b853cdafdef1549be31b478a954f6d8b36d314e6
path: packages/audioplayers_ohos
audioplayers_platform_interface:
git:
url: https://atomgit.com/CPF-Flutter/flutter_audioplayers.git
ref: b853cdafdef1549be31b478a954f6d8b36d314e6
path: packages/audioplayers_platform_interface
执行 flutter pub get 后 import 'package:audioplayers/audioplayers.dart';。
三个注意点:
- 必须用
dependency_overrides:audioplayers 是 federated 插件(主包 + 各平台实现包 + 接口包)。若不锁audioplayers_ohos到同 commit,pub 可能解析到无鸿蒙实现的旧版本,运行时报MissingPluginException path必须写子包路径(packages/audioplayers、packages/audioplayers_ohos),不能只写到仓库根ref写 commit hash(本文b853cda),tag/分支名可能随上游推进漂移
4.2 调用接口实现功能
4.2.1 AudioPlayer 实例与事件订阅
final player = AudioPlayer();
player.onPlayerStateChanged.listen((s) { /* PlayerState.playing 等 */ });
player.onDurationChanged.listen((d) { /* 总时长 */ });
player.onPositionChanged.listen((p) { /* 当前进度 */ });
player.onPlayerComplete.listen((_) { /* 单曲播完 */ });
player.onSeekComplete.listen((_) { /* seek 完成 */ });
运行效果:

demo 首屏(a1):蓝色 AppBar + 灰色停止图标 + 大字"已停止" + PlayerState.stopped + 时间 0:00 / 0:00。下方 seek 进度条、四个控制按钮(播放/暂停/继续/停止)、音量滑条、暗色事件流卡(等待事件)
4.2.2 play / pause / resume / stop:播放控制
功能说明:play(Source) 加载并播放;pause() 暂停;resume() 从暂停处继续;stop() 停止并复位。
// 播放资产音频(pubspec 的 flutter.assets 已声明 assets/audio/)
await player.play(AssetSource('audio/demo.m4a'));
await player.pause(); // 暂停
await player.resume(); // 继续
await player.stop(); // 停止
运行效果:

点击"播放"后(a2):蓝色播放图标 + 大字"播放中" + PlayerState.playing + 时间 0:03 / 0:03(onPositionChanged 每秒刷新)。事件流日志三连:onPlayerStateChanged → playing、play(AssetSource demo.m4a)、onDurationChanged → 3529ms(音频总长 3.5 秒)——三个流全部真实触发
4.2.3 seek + setVolume:进度与音量
功能说明:seek(Duration) 跳转播放位置(触发 onSeekComplete);setVolume(0.0~1.0) 调节音量。
// 进度条拖动到 40% 处
await player.seek(Duration(milliseconds: (0.4 * durationMs).round()));
// 音量调到 60%
await player.setVolume(0.6);
demo 中进度条 Slider.onChanged 直接调 seek,音量滑条实时调 setVolume,两者动作均写入事件流日志。
4.2.4 onPlayerComplete:播放完成
功能说明:音频自然播完时触发(区别于手动 stop())。
player.onPlayerComplete.listen((_) {
print('本条音频播放完成');
// 自动播下一条 / 循环 / 解锁 UI
});
运行效果:

3.5 秒音频自然播完后(a3):绿色勾图标 + 大字"播放完成" + PlayerState.completed + 时间回到 0:00 / 0:03。事件流日志新增 onPlayerComplete(播放完成) 与 onSeekComplete(demo 的 stop 复位触发)——完成事件真实回调到 Dart 层
4.3 完整示例代码
完整工程(含资产音频 assets/audio/demo.m4a)已开源:https://atomgit.com/weixin_52908342/audio_demo,clone 后 flutter pub get && flutter build hap --debug 即可在模拟器复现本文全部效果。
核心状态管理(可复制骨架):
class _AudioPageState extends State<AudioPage> {
late final AudioPlayer _player;
PlayerState _state = PlayerState.stopped;
Duration _pos = Duration.zero, _dur = Duration.zero;
double _volume = 1.0;
final List<StreamSubscription> _subs = [];
void initState() {
super.initState();
_player = AudioPlayer();
_subs.addAll([
_player.onPlayerStateChanged.listen((s) => setState(() => _state = s)),
_player.onDurationChanged.listen((d) => setState(() => _dur = d)),
_player.onPositionChanged.listen((p) => setState(() => _pos = p)),
_player.onPlayerComplete.listen((_) => log('播完')),
_player.onSeekComplete.listen((_) => log('seek 完成')),
]);
}
void dispose() {
for (final s in _subs) { s.cancel(); }
_player.dispose();
super.dispose();
}
Future<void> _play() =>
_player.play(AssetSource('audio/demo.m4a'));
}
签名与构建(活动硬性要求 signingConfig: "default"):
flutter create --platforms ohos .
# ohos/build-profile.json5 的 app.signingConfigs 填入 DevEco 自动签名材料
flutter build hap --debug
hdc install build/ohos/hap/entry-default-signed.hap
hdc shell aa start -b com.example.audio_demo -a EntryAbility
五、FAQ:使用问题
Q1:运行时报 MissingPluginException: No implementation found for method ...
dependency_overrides 没锁 audioplayers_ohos,或锁的 commit 不含 ohos 平台。确认三包(主包 / audioplayers_ohos / audioplayers_platform_interface)都在 overrides 里且 ref 一致(本文 b853cda),然后 flutter clean && flutter pub get 重新构建。
Q2:播放资产音频报 Unable to load asset
pubspec.yaml 的 flutter.assets 段没声明资产目录,或路径大小写不对:
flutter:
assets:
- assets/audio/ # 目录尾斜杠 = 整目录打包
Q3:模拟器上听不到声音
DevEco 模拟器音频输出依赖宿主机——确认 Mac 本身没静音。demo 的 UI 状态与事件流不依赖扬声器(进度/状态照常刷新),本文三张截图即模拟器真实运行效果。
Q4:onDurationChanged 只触发一次,进度不动
onDurationChanged本来就只在加载/时长变化时触发(一次正常)- 进度要看
onPositionChanged(播放中持续推送) - 若
onPositionChanged不动:确认play()成功(状态流先到 playing)、没误调stop()
Q5:连续快速 play 同一资产有杂音/重叠
audioplayers 6.x 单实例复用需先 stop();或使用 AudioPool(低延迟音效场景,提示音/按键音推荐):
final pool = await AudioPool.create(source: AssetSource('audio/click.mp3'));
pool.start();
Q6:鸿蒙端与 Android 端行为差异
- 鸿蒙侧由
audioplayers_ohos基于@ohos.multimedia.media.AVPlayer实现,release()行为与 Android 一致 - 网络播放(
UrlSource)需在module.json5声明ohos.permission.INTERNET(demo 已含) setPlaybackRate/setReleaseMode(循环)在鸿蒙侧的支持进度以 flutter_audioplayers 仓库 的 CHANGELOG.OpenHarmony.md 为准
Q7:发现库的问题怎么反馈?
- 提 Issue:到 CPF-Flutter/flutter_audioplayers → Issues → 新建,正文四要素:复现步骤 / 期望 / 实际 /
flutter --version+ 设备系统版本 + hilog 关键日志 - 提 PR:Fork → 建分支 → 修复提交 → push → 在 AtomGit 发 PR,描述附鸿蒙设备验证截图
六、其他内容
audioplayers 6.5.1 鸿蒙适配版开箱即用:federated 三包锁同一 commit 后,播放控制、seek、音量、五个事件流全部与 Android/iOS 行为一致。Demo 在 DevEco 模拟器(HarmonyOS 7.0.0.106 / API 26)上真实验证了播放→完成全流程,事件流逐条实时回调。对比自研 ArkTS 播放器(AVPlayer 状态机 + 通道桥接),一行 git 依赖就获得跨端一致体验,是鸿蒙 Flutter 应用音频需求的默认选择。
更多推荐




所有评论(0)