Playing the same audio file multiple times - Audioplayers Flutter - flutter

How can I play the same audio file as many times as I want, not loop but I want the possibility to precise how many times, I followed this tutorial to make the basics which mean the play/pause function. And I'm struggling with the rest.
I use the last version of the audioplayers package.
This is my code :
import 'package:flutter/material.dart';
import 'package:audioplayers/audioplayers.dart';
import 'package:audioplayers/audio_cache.dart';
class Player extends StatefulWidget {
#override
_PlayerState createState() => _PlayerState();
}
AnimationController _animationIconController ;
AudioCache audioCache;
AudioPlayer audioPlayer;
bool issongplaying = false;
bool isplaying = false;
class _PlayerState extends State<Player> with TickerProviderStateMixin {
#override
void initState() {
// TODO: implement initState
super.initState();
initPlayer();
}
void initPlayer(){
_animationIconController = AnimationController(
vsync: this,
duration: Duration(milliseconds: 750),
reverseDuration: Duration(milliseconds: 750),
);
audioPlayer = new AudioPlayer();
audioCache = new AudioCache(fixedPlayer: audioPlayer);
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
GestureDetector(
onTap: (){
setState((){
isplaying
? _animationIconController.reverse()
: _animationIconController.forward();
isplaying = !isplaying;
});
if (issongplaying == false) {
audioCache.play('audio.wav');
setState(() {
issongplaying = true;
});
} else {
audioPlayer.pause();
setState(() {
issongplaying = false;
});
}
},
child: ClipOval(
child: Container(
decoration: BoxDecoration(
border: Border.all(
width: 2,
color: Colors.greenAccent,
),
borderRadius: BorderRadius.all(Radius.circular(50.0)
),
),
width: 75,
height: 75,
child: Center(
child: AnimatedIcon(
icon: AnimatedIcons.play_pause,
progress: _animationIconController,
color: Colors.grey,
size: 60,
)
),
),
),
)
],
),
),
);
}
}
Thank you

This might be complex for you but try giving it a shot.
I can see the audioplayers package has the event onPlayerCompletion, which will be called each time you finish playing an audio.
You can tell your player in this event to track the amount of times it ends and set the audio to loop, it will stop when it repeats X times:
int timesPlayed = 0;
int timesToRepeat = 3; //The audio will repeat 3 times
//This method gets called each time your audio finishes playing.
player.onPlayerCompletion.listen((event) {
//Here goes the code that will be called when the audio finishes
onComplete();
setState(() {
position = duration;
timesPlayed++;
if(timesPlayed >= timesToRepeat) {
timesPlayed = 0;
await player.stop();
}
});
});

Related

Flutter - Lottie controller loop breaks when playing the animation twice

I coded a simple Lottie animation state manager. From a pool of lottie-json files, each containing also a probability to play, I select one and set the _index to play that file.
However, if randomly the same file will that played before will be played again, the loop just stops and I have to restart... I depict a minimal example of my code here:
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
final Random rnd = Random();
int _index = 0;
late BechtoAnimation _animation;
late final AnimationController _controller;
#override
void initState() {
super.initState();
_controller = AnimationController(vsync: this)
..addStatusListener((status) {
if(status == AnimationStatus.completed){
setState(() {
int i = 0;
double p = rnd.nextDouble();
double cumulativeProbability = 0.0;
for(AnimationLoop animationLoop in _animation.loop){
cumulativeProbability += animationLoop.probability;
if (p <= cumulativeProbability) {
_index = i;
break;
}
i++;
}
});
}
});
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext buildContext) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
BlocBuilder<MyCubit, MyState>(
builder: (context, state) {
if(state is AnimationLoadedFailure){
return Text(state.toString(), style: const TextStyle(color: Colors.blueGrey));
}else if(state is AnimationLoadedSuccess){
_animation = state.animation;
return SizedBox(
width: 200,
height: 200,
child: Lottie.asset(
state.animation.loop.elementAt(_index).fileName,
width: 200,
height: 200,
fit: BoxFit.fill,
controller: _controller,
onLoaded: (composition){
_controller.duration = composition.duration;
_controller.reset();
_controller.forward();
}
),
);
}else{
return Text(state.toString(), style: const TextStyle(color: Colors.blueGrey));
}
}
)
],
),
));
}
}
As you can see, I select the new animation when the old one is finished via the StatusListener. However, when its the same, everything just stops... Any idea?
Flutter version is: 3.3.0 and my Dart version is 2.18.0

Unhandled Exception: setState() called after dispose() - due to modal dissmissed

I have a modalBottomSheet. On it, I am displaying several widgets, especially an audioPlayer.
I have find out that when I press the play button, the audio file is playing, so far so good, but if I tap outside the modalBottomSheet, the modal is dismissed. I am OK to get the modal dismissed. But my problem is that when it is dismissed, the player which is running, is generating an exception.
Unhandled Exception: setState() called after dispose()
I do not want to make the Modal not dissmisible.
Please, can you advise? Many thanks.
import 'package:audioplayers/audioplayers.dart';
import 'package:audioplayers/audioplayers_api.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:gtd_official_sharped_focused/Reusable%20Widget/Player_Audio/widgets/play_pause_button.dart';
class AudioPlayerWidget extends StatefulWidget {
final String url;
final bool isAsset;
final Duration currentTime;
final Duration totalTime;
final ValueChanged<Duration> onSeekBarMoved;
const AudioPlayerWidget({
Key key,
this.url,
this.isAsset = false,
this.currentTime,
this.totalTime,
this.onSeekBarMoved,
}) : super(key: key);
#override
_AudioPlayerWidgetState createState() => _AudioPlayerWidgetState();
}
class _AudioPlayerWidgetState extends State<AudioPlayerWidget> {
AudioPlayer _audioPlayer;
AudioCache _audioCache;
//variables for slider
Duration _duration = new Duration();
Duration _position = new Duration();
PlayerState _playerState = PlayerState.STOPPED;
bool get _isPlaying => _playerState == PlayerState.PLAYING;
bool get _isLocal => !widget.url.contains('https');
#override
void initState() {
_audioPlayer = AudioPlayer(mode: PlayerMode.MEDIA_PLAYER);
_audioCache = AudioCache(fixedPlayer: _audioPlayer);
_audioPlayer.onDurationChanged.listen((d) {setState(() {
_duration = d;
});});
_audioPlayer.onAudioPositionChanged.listen((p) {setState((){
_position = p;
});});
_audioPlayer.onPlayerCompletion.listen((event) {
setState(() {
_position = Duration(seconds: 0);
_playerState = PlayerState.STOPPED;
});
});
_audioPlayer.onPlayerError.listen((msg) {
print('audioPlayer error : $msg');
setState(() {
_playerState = PlayerState.STOPPED;
});
});
super.initState();
}
#override
void dispose() {
_audioPlayer.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.only(left:18.0),
child: Text(_position.toString().split('.')[0],style:TextStyle(fontSize: 16)),
),
Padding(
padding: const EdgeInsets.only(right:18.0),
child: Text(_duration.toString().split('.')[0],style:TextStyle(fontSize: 16)),
),
],),
_buildSliderBar(context),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
buttonBackWard10Seconds(),
PlayPauseButton(
isPlaying: _isPlaying,
onPlay: () => _playPause()
),
buttonForward10Seconds(),
//Do not delete iconButton below => for reference
/* IconButton(
onPressed: () => _stop(),
icon: Icon(
Icons.stop,
size: 40,
color: Colors.red,
),
),*/
],
),
],
);
}
//########################################################
_playPause() async {
if (_playerState == PlayerState.PLAYING) {
final playerResult = await _audioPlayer.pause();
if (playerResult == 1) {
setState(() {
_playerState = PlayerState.PAUSED;
});
}
} else if (_playerState == PlayerState.PAUSED) {
final playerResult = await _audioPlayer.resume();
if (playerResult == 1) {
setState(() {
_playerState = PlayerState.PLAYING;
});
}
} else {
if (widget.isAsset) {
_audioPlayer = await _audioCache.play(widget.url);
setState(() {
_playerState = PlayerState.PLAYING;
});
} else {
final playerResult = await _audioPlayer.play(widget.url, isLocal: _isLocal);
if (playerResult == 1) {
setState(() {
_playerState = PlayerState.PLAYING;
});
}
}
}
}
void changeToSecond(int second){
Duration newDuration = Duration(seconds:second);
_audioPlayer.seek(newDuration);
}
_stop() async {
final playerResult = await _audioPlayer.stop();
if (playerResult == 1) {
setState(() {
_playerState = PlayerState.STOPPED;
});
}
}
//###############################################################
Slider _buildSliderBar(BuildContext context) {
return Slider(
value: _position.inSeconds.toDouble(),
min: 0.0,
max: _duration.inSeconds.toDouble(), //_sliderValue,
activeColor: Colors.red,
inactiveColor: Colors.grey,
onChanged: (double value) {
setState(() {
changeToSecond(value.toInt());
value=value;
});
},
);
}
Widget buttonBackWard10Seconds(){
return IconButton( icon: Icon(CupertinoIcons.gobackward_10),
iconSize: 40,
color: Colors.black,
onPressed: (){
_position = _position - Duration(seconds:10);
if (_position < Duration(seconds:0)) {
_audioPlayer.seek(Duration(seconds: 0));
}
else {
_audioPlayer.seek(_position);
}});
}
Widget buttonForward10Seconds(){
return IconButton( icon:Icon( CupertinoIcons.goforward_10),
iconSize: 40,
color: Colors.black,
onPressed: (){
_position = _position + Duration(seconds:10);
if (_duration >_position) {
_audioPlayer.seek(_position);
}
else if (_duration <_position) {
_audioPlayer.seek(_duration);
}
}
);
}
}
import 'package:flutter/material.dart';
import 'package:gtd_official_sharped_focused/Reusable%20Widget/Player_Audio/widgets/audio_player_widget.dart';
import 'package:gtd_official_sharped_focused/Services/extract_file_Name_url/extract_file_name_url.dart';
Widget modalBottomPlayAudio (context,String urlToPlay){
showModalBottomSheet(
context: context,
//background color for modal bottom screen
backgroundColor: Colors.white,
//elevates modal bottom screen
elevation: 10,
// gives rounded corner to modal bottom screen
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
builder: (BuildContext context) {
// UDE : SizedBox instead of Container for whitespaces
return SizedBox(
height: 350,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
/*Padding(
padding: const EdgeInsets.all(28.0),
),*/
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(left:18.0),
child: Text(getFileNameFromURL(urlToPlay),
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),),
),
],
),
SizedBox(height: 60,),
AudioPlayerWidget(url:urlToPlay),
],
),
),
);
},
);
}
you could change
setState(()=>{
...
})
to
if(mounted)(
setState(()=>{
...
})
)
Which ensures setState is called only when the widget is mounted on the screen.

flutter:: Is there a way to play only one audio file using the audioplayer package?

I saved the audio files in list 'file'. I want to play this audio file using the audioplayers package. I have listed audio files using listview, but I want to play only one selected audio file among multiple audio files. Currently, the entire audio file in the records is played at the same time and an error has occurred.
How can I solve this?
This is part of my code.
class AudioViewer extends StatefulWidget {
#override
_AudioViewerState createState() => _AudioViewerState();
}
class _AudioViewerState extends State<AudioViewer> {
List file = [];
var audioPath;
var directory;
AudioPlayer? audioPlayer;
bool _isplaying = false;
var _icon = Icons.play_arrow;
var _deleteicon = Icons.delete;
Color _color = Colors.deepOrangeAccent;
Duration position = Duration();
Duration duration = Duration(seconds: 1);
int indexindex = 0;
#override
void initState() {
super.initState();
getFiles();
_setupAudioPlayer();
}
void getFiles() async {
directory = (await getExternalStorageDirectory())!.path;
setState(() {
file = Directory("$directory").listSync();
});
print(file.toString());
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
title: Text(
"Audio List",
),
),
body: Container(
child: ListView.builder(
reverse: true,
itemCount: widget.records.length,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return Card(
elevation: 5,
child: ExpansionTile(
title: Text(
widget.records[index].path.split('/').last.split(".").first,
style: TextStyle(color: Colors.black),
),
onExpansionChanged: ((newState) {
if (newState) {
indexindex = index;
setState(() {
});
}
}),
children: [
Container(
height: 100,
padding: EdgeInsets.fromLTRB(10,0,10,0),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Container(
child: IconButton(
iconSize: 40,
onPressed: () {
if (!_isplaying) {
audioPlayer!.resume();
setState(() {
_isplaying = true;
_icon = Icons.pause;
_color = Colors.blueGrey;
});
} else {
audioPlayer!.release();
setState(() {
position = new Duration();
_isplaying = false;
_icon = Icons.play_arrow;
_color = Colors.deepOrangeAccent;
});
}
},
icon: Icon(_icon),
color: _color,
),
),
Container(
child: IconButton(
iconSize: 30,
onPressed: () {
widget.records[index].delete(recursive: true);
setState(() {
widget.records.removeAt(index);
position = new Duration();
});
},
icon: Icon(_deleteicon),
),
),
]
),
It seems you have your state variables like _isplaying only once for the whole page/list. You need them per song. This doesn't seem to be a complete example (widget.records seems to be missing) so I cannot really help a lot here.
What you could do, if widget.records contains the songs, is to have a currentlyPlaying variable that is the record that is currently playing, instead of just a generic _isplaying. This way, you could figure out if the currectly build list entry is actually playing or not. But then maybe I'm misunderstanding something, since your audioplayer is not actually playing that song, it just resumes whatever it was playing before.
Maybe start out with easy steps and first make the icon work. That should be possible with the method I mentioned above: keep track of which record was selected.
You need to create a globals.dart file like that:
AudioPlayer? _player;
Future<void> playAudio(AudioPlayer player, AudioSource source) async {
if (_player != null && _player!.playing) {
await _player!.stop();
}
_player = player;
player.setAudioSource(source);
player.play();
}
And use it in somewhere:
playAudio(currentAudio, audioSource);

How to play more than one audio file in the same page in flutter?

I have a chat page where a user can send texts, images, audio and video as messages to the other users. Everything works fine except for the Audio and Video. In my chat application, a user is allowed to pick audio files using the file_picker plugin. After the user picks an audio file, it is then uploaded to a server. The server than sends back the audio file using a socket event. My app listens to the socket event and generates the message view depending on the type of messages. If its a text message, it is shown in a text widget. If its a audio message, it is shown in an audio widget. audio_player plugin is used to play the audio file. When the user uploads an audio, after a little time the audio file is shown to both the users chatting in the same room. Everything works fine if it is a single audio file. If the user uploads another audio file as in a 2nd audio, the audio controller replaces all my audio files in the chat view with the last audio uploaded. The code used for audio is below:
//for audio files (This code has been placed in _ChatPageState)
AnimationController _animationIconController1;
AudioCache audioCache;
AudioPlayer audioPlayer;
Duration _duration = new Duration();
Duration _position = new Duration();
Duration _slider = new Duration(seconds: 0);
double durationValue;
bool isSongPlaying = false;
bool isPlaying = false;
Later, the variables are initialsed in initState()
//for audio inside initState
_position = _slider;
_animationIconController1 = AnimationController(
vsync: this,
duration: Duration(milliseconds: 750),
reverseDuration: Duration(milliseconds: 750),
);
audioPlayer = new AudioPlayer();
audioCache = new AudioCache(fixedPlayer: audioPlayer);
audioPlayer.durationHandler = (d) => setState(() {
_duration = d;
});
audioPlayer.positionHandler = (p) => setState(() {
_position = p;
});
Next, if the user receives a audio file from socket listener an audio widget is presented, so that the users can play the file:
Widget audioMessage(int index) {
return Container(
width: MediaQuery.of(context).size.width * 0.6,
height: 30,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
GestureDetector(
onTap: () {
setState(() {
isPlaying ? _animationIconController1.reverse() : _animationIconController1.forward();
isPlaying = !isPlaying;
});
// Add code to pause and play the music.
if (!isSongPlaying){
audioPlayer.play('some hidden link/file/${messages[index].message}');
setState(() {
isSongPlaying = true;
});
} else {
audioPlayer.pause();
setState(() {
isSongPlaying = false;
});
}
},
child: ClipOval(
child: Container(
color: Colors.pink[600],
child: Padding(
padding: const EdgeInsets.all(8.0),
child: AnimatedIcon(
icon: isSongPlaying ==false ? AnimatedIcons.play_pause : AnimatedIcons.pause_play,
size: 14,
progress: _animationIconController1,
color: Colors.white,
),
),
),
),
),
Slider(
activeColor: Colors.white,
inactiveColor: Colors.grey,
value: _position.inSeconds.toDouble(),
max: _duration.inSeconds.toDouble(),
onChanged: (double value) {
seekToSeconds(value.toInt());
value = value;
},
),
],
),
);
}
I think the problem is with my audio and animation controllers. It is only initiated for only one player. So how can i go around this problem. A user can upload as many audios as he wants. How can i dynamically create audio controllers for as many audio files that are uploaded by the user?
So, I have accomplished this by moving all my audio codes into a separate dart file. See below for audio implementation:
class PlayAudio extends StatefulWidget {
final String url;
const PlayAudio({Key key, this.url}) : super(key: key);
#override
_PlayAudioState createState() => _PlayAudioState();
}
class _PlayAudioState extends State<PlayAudio> with TickerProviderStateMixin{
//for audio files
AnimationController _animationIconController1;
AudioCache audioCache;
AudioPlayer audioPlayer;
Duration _duration = new Duration();
Duration _position = new Duration();
Duration _slider = new Duration(seconds: 0);
double durationValue;
bool isSongPlaying = false;
bool isPlaying = false;
#override
void initState() {
// TODO: implement initState
super.initState();
//for audio inside initState
_position = _slider;
_animationIconController1 = new AnimationController(
vsync: this,
duration: new Duration(milliseconds: 750),
reverseDuration: new Duration(milliseconds: 750),
);
audioPlayer = new AudioPlayer();
audioCache = new AudioCache(fixedPlayer: audioPlayer);
audioPlayer.durationHandler = (d) => setState(() {
_duration = d;
});
audioPlayer.positionHandler = (p) => setState(() {
_position = p;
});
print('audio widget: ' + widget.url);
}
#override
void dispose() {
// TODO: implement dispose
super.dispose();
audioPlayer.dispose();
}
void seekToSeconds(int second) {
Duration newDuration = Duration(seconds: second);
audioPlayer.seek(newDuration);
}
#override
Widget build(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width * 0.6,
height: 30,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
GestureDetector(
onTap: () {
setState(() {
isPlaying ? _animationIconController1.reverse() : _animationIconController1.forward();
isPlaying = !isPlaying;
});
// Add code to pause and play the music.
if (!isSongPlaying){
audioPlayer.play('${widget.url}');
setState(() {
isSongPlaying = true;
});
} else {
audioPlayer.pause();
setState(() {
isSongPlaying = false;
});
}
},
child: ClipOval(
child: Container(
color: Colors.pink[600],
child: Padding(
padding: const EdgeInsets.all(8.0),
child: AnimatedIcon(
icon: AnimatedIcons.play_pause,
size: 14,
progress: _animationIconController1,
color: Colors.white,
),
),
),
),
),
Slider(
activeColor: Colors.white,
inactiveColor: Colors.grey,
value: _position.inSeconds.toDouble(),
max: _duration.inSeconds.toDouble(),
onChanged: (double value) {
seekToSeconds(value.toInt());
value = value;
},
),
],
),
);
}
}
This is now a separate class. Now, to play multiple audio files all I am doing is calling the above file into my main.dart wherever it is needed. Make sure you call 'new' everytime you want to play a new audio file, just pass an url. See below:
new PlayAudio(url: 'some URL');
Hope this helps to play multiple audio files in the same page. FYI, i am using https://pub.dev/packages/audioplayers

play audio file from where i pause, not from the beginning in Audioplayers flutter package

i am new in flutter ... I want to play audio file from where i pause, not from the beginning in audioplayers flutter package ...
in this example there is just:
1- play from the beginning
2- pause
3- stop
pause and stop they have same function because by pause i can not play from where i pause ...
so what i want is to play from where i pause, in same button!
the audioplayers package which I use
https://pub.dev/packages/audioplayers
my code ...
import 'package:audioplayers/audio_cache.dart';
import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';
typedef void OnError(Exception exception);
void main() {
runApp(new MaterialApp(debugShowCheckedModeBanner: false,home: LocalAudio()));
}
class LocalAudio extends StatefulWidget {
#override
_LocalAudio createState() => _LocalAudio();
}
class _LocalAudio extends State<LocalAudio> {
Duration _duration = new Duration();
Duration _position = new Duration();
AudioPlayer advancedPlayer;
AudioCache audioCache;
#override
void initState() {
super.initState();
initPlayer();
}
void initPlayer() {
advancedPlayer = new AudioPlayer();
audioCache = new AudioCache(fixedPlayer: advancedPlayer);
advancedPlayer.durationHandler = (d) => setState(() {
_duration = d;
});
advancedPlayer.positionHandler = (p) => setState(() {
_position = p;
});
}
String localFilePath;
Widget _tab(List<Widget> children) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
padding: EdgeInsets.all(16.0),
child: Column(
children: children
.map((w) => Container(child: w, padding: EdgeInsets.all(6.0)))
.toList(),
),
),
],
);
}
Widget _btn(String txt, VoidCallback onPressed) {
return ButtonTheme(
minWidth: 48.0,
child: Container(
width: 150,
height: 45,
child: RaisedButton(
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(25)),
child: Text(txt),
color: Colors.pink[900],
textColor: Colors.white,
onPressed: onPressed),
),
);
}
Widget slider() {
return Slider(
activeColor: Colors.black,
inactiveColor: Colors.pink,
value: _position.inSeconds.toDouble(),
min: 0.0,
max: _duration.inSeconds.toDouble(),
onChanged: (double value) {
setState(() {
seekToSecond(value.toInt());
value = value;
});
});
}
Widget LocalAudio() {
return _tab([
_btn('Play', () => audioCache.play('disco.mp3')),
_btn('Pause', () => advancedPlayer.pause()),
_btn('Stop', () => advancedPlayer.stop()),
slider()
]);
}
void seekToSecond(int second) {
Duration newDuration = Duration(seconds: second);
advancedPlayer.seek(newDuration);
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 1,
child: Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
elevation: 1.0,
backgroundColor: Colors.teal,
title: Center(child: Text('LOCAL AUDIO')),
),
body: TabBarView(
children: [LocalAudio()],
),
),
);
}
}
You can use the resume method to play the audio from where you paused it.
await audioPlayer.resume();
It only works if the audioPlayer state is Paused.
From the package documentation:
Also, you can resume (like play, but without new parameters):
int result = await audioPlayer.resume();
there is a function in class AudioPlayer for resume
it is look like this in class AudioPlayer
Future<int> resume() async {
final int result = await _invokeMethod('resume');
if (result == 1) {
state = AudioPlayerState.PLAYING;
}
return result;
}
to use it add
_btn('resume', () => advancedPlayer.resume()),
below line of
_btn('Pause', () => advancedPlayer.pause()),