fluttertpc_just_audio 在鸿蒙上的使用指南
fluttertpc_just_audio是专为鸿蒙系统适配的Flutter音频播放插件,基于just_audio开发。该插件提供完整的音频播放功能,包括加载网络音频、播放控制、音量调节、速度设置和进度定位等核心功能。安装方式简单,只需在pubspec.yaml中添加依赖即可。插件包含AudioPlayer核心类,提供初始化、加载、播放、暂停等主要方法,并支持多种状态监听流。示例代码展示了如何实现
一、插件介绍
fluttertpc_just_audio 是基于 just_audio 开发的鸿蒙系统适配版本,为 Flutter 开发者提供在鸿蒙平台上进行音频播放的强大功能。该插件支持音频的加载、播放、暂停、音量控制、速度调节等核心功能,帮助开发者轻松实现音频播放需求。
主要特性
- 支持从网络 URI 加载音频资源
- 提供播放/暂停控制
- 支持音量调节和播放速度控制
- 实现音频进度条和定位功能
- 支持多音频源的串联播放
- 基于原生鸿蒙实现,性能优秀
二、安装与配置
1. 添加依赖
在项目的 pubspec.yaml 文件中添加以下依赖:
dependencies:
just_audio_ohos:
git:
url: "https://gitcode.com/openharmony-sig/fluttertpc_just_audio"
path: "just_audio/ohos"
执行以下命令获取依赖:
flutter pub get
2. 配置音频会话(可选)
根据需要,可以配置音频会话以适应不同的音频播放场景(如音乐、语音等):
import 'package:audio_session/audio_session.dart';
final session = await AudioSession.instance;
await session.configure(const AudioSessionConfiguration.speech());
三、API 说明
核心类
AudioPlayer
音频播放器的核心类,用于控制音频的加载、播放、暂停等操作。
主要方法
| 方法名 | 描述 | 返回值 | 鸿蒙支持 |
|---|---|---|---|
init() |
创建一个新的平台播放器 | Future<AudioPlayerPlatform> |
yes |
load() |
加载音频源 | Future<LoadResponse> |
yes |
play() |
在当前位置播放音频 | Future<PlayResponse> |
yes |
pause() |
暂停播放 | Future<PauseResponse> |
yes |
setVolume() |
设置音量(0.0-1.0) | Future<SetVolumeResponse> |
yes |
setSpeed() |
设置播放速度 | Future<SetSpeedResponse> |
yes |
seek() |
定位到指定位置 | Future<SeekResponse> |
yes |
disposePlayer() |
释放播放器资源 | Future<DisposePlayerResponse> |
yes |
主要流
| 流名称 | 描述 | 鸿蒙支持 |
|---|---|---|
positionStream |
播放位置流 | yes |
bufferedPositionStream |
缓冲位置流 | yes |
durationStream |
音频时长流 | yes |
playbackEventStream |
播放事件流 | yes |
playerStateStream |
播放器状态流 | yes |
四、使用示例
完整示例代码
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:just_audio/just_audio.dart';
import 'package:rxdart/rxdart.dart';
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
MyAppState createState() => MyAppState();
}
class MyAppState extends State<MyApp> {
final _player = AudioPlayer();
void initState() {
super.initState();
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
statusBarColor: Colors.black,
));
_initPlayer();
}
Future<void> _initPlayer() async {
// 监听播放错误
_player.playbackEventStream.listen((event) {},
onError: (Object e, StackTrace stackTrace) {
print('播放错误: $e');
});
// 加载音频源
try {
await _player.setAudioSource(AudioSource.uri(Uri.parse(
"https://s3.amazonaws.com/scifri-episodes/scifri20181123-episode.mp3")));
} on PlayerException catch (e) {
print("加载音频失败: $e");
}
}
void dispose() {
_player.dispose();
super.dispose();
}
/// 组合位置、缓冲位置和时长流,用于显示进度条
Stream<PositionData> get _positionDataStream =>
Rx.combineLatest3<Duration, Duration, Duration?, PositionData>(
_player.positionStream,
_player.bufferedPositionStream,
_player.durationStream,
(position, bufferedPosition, duration) => PositionData(
position, bufferedPosition, duration ?? Duration.zero));
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
// 播放控制按钮
ControlButtons(_player),
// 进度条
StreamBuilder<PositionData>(
stream: _positionDataStream,
builder: (context, snapshot) {
final positionData = snapshot.data;
return SeekBar(
duration: positionData?.duration ?? Duration.zero,
position: positionData?.position ?? Duration.zero,
bufferedPosition: positionData?.bufferedPosition ?? Duration.zero,
onChangeEnd: _player.seek,
);
},
),
],
),
),
),
);
}
}
/// 播放控制按钮组件
class ControlButtons extends StatelessWidget {
final AudioPlayer player;
const ControlButtons(this.player, {Key? key}) : super(key: key);
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
// 音量控制
IconButton(
icon: const Icon(Icons.volume_up),
onPressed: () {
showSliderDialog(
context: context,
title: "调整音量",
divisions: 10,
min: 0.0,
max: 1.0,
value: player.volume,
stream: player.volumeStream,
onChanged: player.setVolume,
);
},
),
// 播放/暂停按钮
StreamBuilder<PlayerState>(
stream: player.playerStateStream,
builder: (context, snapshot) {
final playerState = snapshot.data;
final processingState = playerState?.processingState;
final playing = playerState?.playing;
// 加载或缓冲中显示进度指示器
if (processingState == ProcessingState.loading ||
processingState == ProcessingState.buffering) {
return Container(
margin: const EdgeInsets.all(8.0),
width: 64.0,
height: 64.0,
child: const CircularProgressIndicator(),
);
}
// 未播放状态显示播放按钮
else if (playing != true) {
return IconButton(
icon: const Icon(Icons.play_arrow),
iconSize: 64.0,
onPressed: player.play,
);
}
// 播放中显示暂停按钮
else if (processingState != ProcessingState.completed) {
return IconButton(
icon: const Icon(Icons.pause),
iconSize: 64.0,
onPressed: player.pause,
);
}
// 播放完成显示重播按钮
else {
return IconButton(
icon: const Icon(Icons.replay),
iconSize: 64.0,
onPressed: () => player.seek(Duration.zero),
);
}
},
),
// 播放速度控制
StreamBuilder<double>(
stream: player.speedStream,
builder: (context, snapshot) => IconButton(
icon: Text("${snapshot.data?.toStringAsFixed(1)}x",
style: const TextStyle(fontWeight: FontWeight.bold)),
onPressed: () {
showSliderDialog(
context: context,
title: "调整播放速度",
divisions: 10,
min: 0.5,
max: 1.5,
value: player.speed,
stream: player.speedStream,
onChanged: player.setSpeed,
);
},
),
),
],
);
}
}
/// 进度条组件
class SeekBar extends StatefulWidget {
final Duration duration;
final Duration position;
final Duration bufferedPosition;
final ValueChanged<Duration>? onChanged;
final ValueChanged<Duration>? onChangeEnd;
const SeekBar({
Key? key,
required this.duration,
required this.position,
required this.bufferedPosition,
this.onChanged,
this.onChangeEnd,
}) : super(key: key);
_SeekBarState createState() => _SeekBarState();
}
class _SeekBarState extends State<SeekBar> {
double? _dragValue;
Widget build(BuildContext context) {
return Stack(
children: [
Slider(
min: 0.0,
max: widget.duration.inMilliseconds.toDouble(),
value: widget.bufferedPosition.inMilliseconds.toDouble(),
onChanged: (value) {
setState(() {
_dragValue = value;
});
widget.onChanged?.call(Duration(milliseconds: value.round()));
},
onChangeEnd: (value) {
widget.onChangeEnd?.call(Duration(milliseconds: value.round()));
_dragValue = null;
},
activeColor: Colors.blue.shade200,
inactiveColor: Colors.grey.shade300,
),
Slider(
min: 0.0,
max: widget.duration.inMilliseconds.toDouble(),
value: _dragValue ?? widget.position.inMilliseconds.toDouble(),
onChanged: (value) {
setState(() {
_dragValue = value;
});
widget.onChanged?.call(Duration(milliseconds: value.round()));
},
onChangeEnd: (value) {
widget.onChangeEnd?.call(Duration(milliseconds: value.round()));
_dragValue = null;
},
activeColor: Colors.blue,
inactiveColor: Colors.transparent,
),
],
);
}
}
/// 滑块对话框组件
void showSliderDialog({
required BuildContext context,
required String title,
required int divisions,
required double min,
required double max,
String valueSuffix = '',
required double value,
required Stream<double> stream,
required ValueChanged<double> onChanged,
}) {
showDialog<void>(
context: context,
builder: (context) => AlertDialog(
title: Text(title, textAlign: TextAlign.center),
content: StreamBuilder<double>(
stream: stream,
builder: (context, snapshot) => SizedBox(
height: 100.0,
child: Column(
children: [
Text('${snapshot.data?.toStringAsFixed(1)}$valueSuffix',
style: const TextStyle(
fontFamily: 'Fixed',
fontWeight: FontWeight.bold,
fontSize: 24.0)),
Slider(
divisions: divisions,
min: min,
max: max,
value: snapshot.data ?? value,
onChanged: onChanged,
),
],
),
),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('关闭'),
),
],
),
);
}
/// 位置数据类
class PositionData {
final Duration position;
final Duration bufferedPosition;
final Duration duration;
PositionData(this.position, this.bufferedPosition, this.duration);
}
关键步骤说明
-
初始化播放器
创建AudioPlayer实例,配置音频会话,并加载音频源。 -
播放控制
通过play()和pause()方法控制音频的播放状态。 -
音量和速度调节
使用setVolume()和setSpeed()方法调整音频的音量和播放速度。 -
进度控制
通过positionStream、bufferedPositionStream和durationStream实时获取播放进度,并使用seek()方法定位到指定位置。 -
资源管理
在组件销毁时调用dispose()方法释放播放器资源。
五、鸿蒙平台注意事项
-
兼容性要求
- Flutter 版本:3.7.12-ohos-1.0.6 或 3.22.1-ohos-1.0.1
- HarmonyOS SDK:5.0.0(12)
- DevEco Studio:5.0.13.200
-
不支持的功能
- 循环播放模式
- 随机播放模式
- 音调控制
- 跳过静音功能
- 音频效果(均衡器、响度增强器等)
- 网络音频元数据获取
-
音频源支持
目前主要支持从网络 URI 加载音频资源,本地文件支持可能有限。
六、总结
fluttertpc_just_audio 是一个功能强大的音频播放插件,为鸿蒙平台提供了核心的音频播放能力。虽然在鸿蒙平台上某些高级功能尚未支持,但已经能够满足大多数基础音频播放需求。开发者可以通过简单的 API 调用实现音频的加载、播放、暂停、音量控制等功能,快速构建音频应用。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐




所有评论(0)