I'm working on a Flutter project in which I want to show an audio recorder and an audio player (separate) on the same screen. At this point I'm just trying things out in an amateur sort of way, as you can see in the code. The 'SimpleRecorder' has been copied from PubDev as is the case with' Audiocache' for the player. I suspect that the 'initstate' appearing twice causes the problem but I don't know how to fix this. Can anyone help?
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_sound_lite/flutter_sound.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:audioplayers/audio_cache.dart';
import 'package:audioplayers/audioplayers.dart';
typedef _Fn = void Function();
class SimpleRecorder extends StatefulWidget {
@override
_SimpleRecorderState createState() => _SimpleRecorderState();
}
class _SimpleRecorderState extends State<SimpleRecorder> {
FlutterSoundPlayer _mPlayer = FlutterSoundPlayer();
FlutterSoundRecorder _mRecorder = FlutterSoundRecorder();
bool _mPlayerIsInited = false;
bool _mRecorderIsInited = false;
bool _mplaybackReady = false;
String _mPath;
@override
void initState() {
// Be careful : openAudioSession return a Future.
// Do not access your FlutterSoundPlayer or FlutterSoundRecorder before the completion of the Future
_mPlayer.openAudioSession().then((value) {
setState(() {
_mPlayerIsInited = true;
});
});
openTheRecorder().then((value) {
setState(() {
_mRecorderIsInited = true;
});
});
super.initState();
}
@override
void dispose() {
stopPlayer();
_mPlayer.closeAudioSession();
_mPlayer = null;
stopRecorder();
_mRecorder.closeAudioSession();
_mRecorder = null;
if (_mPath != null) {
var outputFile = File(_mPath);
if (outputFile.existsSync()) {
outputFile.delete();
}
}
super.dispose();
}
Future<void> openTheRecorder() async {
var status = await Permission.microphone.request();
if (status != PermissionStatus.granted) {
throw RecordingPermissionException('Microphone permission not granted');
}
var tempDir = await getTemporaryDirectory();
_mPath = '${tempDir.path}/flutter_sound_example.aac';
var outputFile = File(_mPath);
if (outputFile.existsSync()) {
await outputFile.delete();
}
await _mRecorder.openAudioSession();
_mRecorderIsInited = true;
}
// ---------------------- Here is the code for recording and playback -------
Future<void> record() async {
assert(_mRecorderIsInited && _mPlayer.isStopped);
await _mRecorder.startRecorder(
toFile: _mPath,
codec: Codec.aacADTS,
);
setState(() {});
}
Future<void> stopRecorder() async {
await _mRecorder.stopRecorder();
_mplaybackReady = true;
}
void play() async {
assert(_mPlayerIsInited &&
_mplaybackReady &&
_mRecorder.isStopped &&
_mPlayer.isStopped);
await _mPlayer.startPlayer(
fromURI: _mPath,
codec: Codec.aacADTS,
whenFinished: () {
setState(() {});
});
setState(() {});
}
Future<void> stopPlayer() async {
await _mPlayer.stopPlayer();
}
// ----------------------------- UI --------------------------------------------
_Fn getRecorderFn() {
if (!_mRecorderIsInited || !_mPlayer.isStopped) {
return null;
}
return _mRecorder.isStopped
? record
: () {
stopRecorder().then((value) => setState(() {}));
};
}
_Fn getPlaybackFn() {
if (!_mPlayerIsInited || !_mplaybackReady || !_mRecorder.isStopped) {
return null;
}
return _mPlayer.isStopped
? play
: () {
stopPlayer().then((value) => setState(() {}));
};
}
//this is where the audio player starts. initState gives an error (has already been defined).
@override
Widget build(BuildContext context) {
Widget makeBody() {
return Column(
children: [
Container(
margin: const EdgeInsets.all(3),
padding: const EdgeInsets.all(3),
height: 80,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Color(0xFFFAF0E6),
border: Border.all(
color: Colors.indigo,
width: 3,
),
),
child: Row(children: [
RaisedButton(
onPressed: getRecorderFn(),
color: Colors.white,
disabledColor: Colors.grey,
child: Text(_mRecorder.isRecording ? 'Stop' : 'Record'),
),
SizedBox(
width: 20,
),
Text(_mRecorder.isRecording
? 'Recording in progress'
: 'Recorder is stopped'),
]),
),
Container(
margin: const EdgeInsets.all(3),
padding: const EdgeInsets.all(3),
height: 80,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Color(0xFFFAF0E6),
border: Border.all(
color: Colors.indigo,
width: 3,
),
),
child: Row(children: [
RaisedButton(
onPressed: getPlaybackFn(),
color: Colors.white,
disabledColor: Colors.grey,
child: Text(_mPlayer.isPlaying ? 'Stop' : 'Play'),
),
SizedBox(
width: 20,
),
Text(_mPlayer.isPlaying
? 'Playback in progress'
: 'Player is stopped'),
]),
),
],
);
}
return Scaffold(
);
}
}
class SoundButton extends StatefulWidget {
@override
_SoundButtonState createState() => _SoundButtonState();
}
class _SoundButtonState extends State<SoundButton> {
AudioCache _audioCache;
@override
void initState() {
super.initState();
// create this only once
_audioCache = AudioCache(prefix: "assets/", fixedPlayer: AudioPlayer()
..setReleaseMode(ReleaseMode.STOP));
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blue,
appBar: AppBar(
title: const Text('Simple Recorder'),
),
body: Row(
children: [
Container(
alignment: Alignment.centerLeft,
margin: const EdgeInsets.all(3),
padding: const EdgeInsets.all(5),
color: Colors.blue,
height: 65,
width: 300,
child: Row(
children: [
RaisedButton
(onPressed: () => _audioCache.play('hello_and_welcome.mp4'),
child:Icon(Icons.arrow_right),
color: Colors.grey[400],
),
SizedBox(width:10),
Text('Hello and Welcome.
'
'Xin Ciao udj anll.'),
],
),
)
],
),
);
}
}
question from:
https://stackoverflow.com/questions/65882922/audio-recorder-and-audio-player-on-same-screen