Flutter中如何使用Audioplayers播放音频
目前在flutter中,并没有官方提供的音频播放插件,因此,需要我们自己去寻找第三方的widget或者自己开发。在google的时候,如果搜索“flutter audio”,那么出来的第一条结果一般都是“audioplayers | Flutter Package - Dart Pub”。本文主要是翻译该项目的说明文件,用来简化大家对它的理解。
原文地址:https://github.com/luanpotter/audioplayers/blob/master/README.md
AudioPlayers
一个可用来同时播放多个音频文件的Flutter插件,兼容Android和iOS。

安装
这个项目是从rxlabz的audioplayer项目fork出来的,名字改成了audioplayers。使用前需要在pubspec.yaml文件中增加如下依赖:
dependencies:
audioplayers: ^0.13.1Discord频道
官方在Fireslime的discord提供了一个交流的频道,可以一起参与进来。
疑难问题
在提交issue前,请先看一下疑难解答。
用法
一个AudioPlayer示例只能同时播放一个音频。可以简单通过构造函数初始化:
AudioPlayer audioPlayer = AudioPlayer();要使用低延迟API(非常适合游戏音频),可以增加mode参数的设置:
AudioPlayer audioPlayer = AudioPlayer(mode: PlayerMode.LOW_LATENCY);在这种模式下,后台不会对总长度和播放位置进行相应通知。当然,也不能通过寻址的方式从某个特殊位置开始播放。
你可以创建多个实例用来同时播放多个音频。
对于所有方法而言,返回类型都是Future1,表示操作成功,否则将返回平台相关的错误码。
默认情况下,日志是被禁用的。如果需要调试,可以增加相应设置:
AudioPlayer.logEnabled = true;播放音频
音频的资源有三种可能性:
- 互联网上的远程文件;
- 用户设备上的本地文件;
- Flutter项目的本地资源。
对于远程和本地文件而言,都使用play方法即可,只需要设置匹配的isLocal标识即可。
对于本地资源,你需要使用AudioCache这个类(而不是AudioPlayer,后面会有介绍)。
要播放一个远程文件,调用call方法时将网址传入即可(isLocal参数默认为false):
如果你需要长时间播放音频,你需要根据情况设置参数stayAwake。当stayAwake参数为true,你需要在manifest增加权限:
<uses-permission android:name="android.permission.WAKE_LOCK" />
play() async {
int result = await audioPlayer.play(url);
if (result == 1) {
// success
}
}如果是本地文件,则需要设置isLocal参数:
playLocal() async {
int result = await audioPlayer.play(localPath, isLocal: true);
}isLocal参数必须设置,是因为在iOS有一些不同(Android没有任何区别)。
你可以通过调用setVolume方法在任意时间调整音量。
控制
正在播放的时候,你可以通过pause、stop和seek方法控制音频。
pause用来暂停播放,但会保留播放位置。随后调用play将继续从暂停的位置开始播放。
int result = await audioPlayer.pause();stop方法将停止音频的播放,且将播放位置重置。随后再调用play时将从开始位置播放。
int result = await audioPlayer.stop();最后,使用seek方法用来对音频进行跳转。
int result = await audioPlayer.seek(Duration(milliseconds: 1200));然后,你也可以使用resume方法(和play类型,但是不需要新参数):
int result = await audioPlayer.resume();精细控制
默认情况下,一旦音频播放完毕,或者stop方法被调用后,播放器将被释放。
这是因为在Android平台,一个MediaPlayer实例占用的资源很多,如果你播放大量音频不释放掉将会导致性能问题。
对于iOS来说不会申请资源,因此释放也不用做什么事情。
你可以修改释放模式,进而改变MediaPlayer结束或停止后的行为。有三个选项:
RELEASE:默认模式,结束或停止后将被释放。STOP:永远不会被释放;需要尽快调用play方法。LOOP:永远不会被释放;当完成后,会循环播放。
如果不是在RELEASE模式,你需要自己调用release方法。比如:
await audioPlayer.setUrl('clicking.mp3'); // prepare the player with this audio but do not start playing
await audioPlayer.setReleaseMode(ReleaseMode.STOP); // set release mode so that it never releases
// 点击按钮时
await audioPlayer.resume(); // 快速播放声音,不会释放
// 退出屏幕时
await audioPlayer.release(); // 不需要时手动释放尽管Android的MediaPlayer的状态图很复杂,但是AudioPlayer实例永远不应该有无效(invalid)的状态。即使它被释放,如果resume被调用,数据也会被重新拉取。
流
AudioPlayer支持订阅这样的事件:
时长事件
当文件可用时,此事件返回文件的时长(可能需要等待一段时间,因为正在下载或缓冲文件)。
player.onDurationChanged.listen((Duration d) {
print('Max duration: $d');
setState(() => duration = d);
});位置事件
此事件更新音频的当前播放位置。例如,你可以使用它来创建一个进度条。
player.onAudioPositionChanged.listen((Duration p) => {
print('Current position: $p');
setState(() => position = p);
});状态事件
此事件返回当前播放器状态。你可以用它来显示播放器是否在播放,或停止,或暂。
player.onPlayerStateChanged.listen((AudioPlayerState s) => {
print('Current player state: $s');
setState(() => palyerState = s);
});完成状态
当音频结束播放时调用此事件。例如,它在loop方法中使用。
当使用pause或者stop方法中断播放时不会产生该事件。
player.onPlayerCompletion.listen((event) {
onComplete();
setState(() {
position = duration;
});
});错误事件
当在本地代码中抛出意外错误时,将调用此函数。
player.onPlayerError.listen((msg) {
print('audioPlayer error : $msg');
setState(() {
playerState = PlayerState.stopped;
duration = Duration(seconds: 0);
position = Duration(seconds: 0);
});
});AudioCache
为了播放本地资源,你必须使用AudioCache类。
Flutter并没有提供对资源播放音频的简单方法,而这个类则提供了相应的方法。它实际上会将资源复制到设备中的一个临时文件夹中,然后将其作为本地文件播放。
它跟踪复制出来的文件,以缓存的形式工作,以便你可以毫不延迟地重播它们。
你可以在这里查看它的详细文档。
支持格式
你可以查看以下支持的格式列表:
⚠️ iOS应用安全传输
默认情况下,iOS禁止从非https的网址加载。要取消此限制,你必须编辑.pl
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
过来看看,学习学习