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.1
Discord频道
官方在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>
过来看看,学习学习