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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.