Flutter Audio Recording Example
Last updated Jul 24, 2021In this post we are going to create Flutter Audio Recording application. To record audio we create a class and to play audio file we used audioplayers plugin. We have updated all plugins to null safety
In this example we will cover
- Record Audio
- Save the Recorded Audio file
- Fetch and Display all Recodrings
- Share the recodrings with other applcations
Step 1: Create a Flutter application
Step 2: Add required dependencies
In this Audio recording app we were used below dependencies
rflutter_alert: ^2.0.2
audioplayers: ^0.19.1
path_provider: ^2.0.2
fluttertoast: ^8.0.7
share: ^2.0.4
permission_handler: ^8.1.4+1
|
Step 3: Import flutter_audio_recorder into dart file by
import 'package:flutter_audio_recorder/flutter_audio_recorder.dart';
Step 4: To work with Audio recording feature we need to grant permissions
In Android Manifest file add below permissions
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
To Read External storage permission in Android 10 we need to add
|
under application tag
This Audio recording plugin support below types
AAC | .m4a .aac .mp4 |
WAV | .wav |
Record Audio
To Record Audio we need to create FlutterAudioRecorder instance
|
To Start the Recording
|
Save the Recorded Audio file
Once we done with our recording, we just stop the recording by
|
This result object will return file path what we given on the initializing the FlutterAudioRecord object
"file_path.mp4"
Fetch and Display all Recordings
To fetch the saved recordings we need to pass out file directory path to Directory class .
This will return list of files inside the folder
getExternalStorageDirectory().then((value) {
appDir = value.;
Directory appDirec = Directory("${appDir.path}/Audiorecords/");
appDir = appDirec;
appDir.list().listen((onData) {
records.add(onData.path);
}).onDone(() {
records = records.reversed.toList();
setState(() {});
});
});
|
Share Audio
To share any file or text we used share: ^0.6.5+4 plugin.To share particular audio recording we need to pass its path to
Share.shareFiles(list)
This Share Files will take the List of file paths as parameter.
Directory appDirec =
Directory(widget.records.elementAt(i));
List<String>list=List();
list.add(appDirec.path);
Share.shareFiles(list);
|
Complete Example of Audio Recording Application
home.dart file
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'list.dart';
import 'view.dart';
class HomePage extends StatefulWidget {
final String _appTitle;
const HomePage({Key? key, required String title})
: assert(title != null),
_appTitle = title,
super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
late Directory? appDir;
late List<String>? records;
@override
void initState() {
super.initState();
records = [];
getExternalStorageDirectory().then((value) {
appDir = value!;
Directory appDirec = Directory("${appDir!.path}/Audiorecords/");
appDir = appDirec;
appDir!.list().listen((onData) {
records!.add(onData.path);
}).onDone(() {
records = records!.reversed.toList();
setState(() {});
});
});
}
@override
void dispose() {
appDir = null;
records = null;
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: (){},
child: InkWell(child: Icon(Icons.mic),onTap: (){
show(context);},),
),
appBar: AppBar(
title: Text(
widget._appTitle,
style: TextStyle(color: Colors.white),
),
centerTitle: true,
),
body: Column(
children: [
Expanded(
flex: 2,
child: Records(
records: records!,
),
),
],
),
);
}
_onFinish() {
records!.clear();
print(records!.length.toString());
appDir!.list().listen((onData) {
records!.add(onData.path);
}).onDone(() {
records!.sort();
records = records!.reversed.toList();
setState(() {});
});
}
void show(BuildContext context) {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return Container(
height: 200,
color: Colors.white70,
child: Recorder(
save: _onFinish,
),
);
},
);
}
}
|
list.dart file
import 'dart:io';
import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:share/share.dart';
class Records extends StatefulWidget {
final List<String> records;
const Records({
Key? key,
required this.records,
}) : super(key: key);
@override
_RecordsState createState() => _RecordsState();
}
class _RecordsState extends State<Records> {
late int _totalTime;
late int _currentTime;
double _percent = 0.0;
int _selected = -1;
bool isPlay=false;
AudioPlayer advancedPlayer = AudioPlayer();
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: widget.records.length,
shrinkWrap: true,
reverse: true,
itemBuilder: (BuildContext context, int i) {
return Card(
elevation: 5,
child: ExpansionTile(
title: Text(
'Record ${widget.records.length - i}',
style: TextStyle(color: Colors.black),
),
subtitle: Text(
_getTime(filePath: widget.records.elementAt(i)!),
style: TextStyle(color: Colors.black38),
),
onExpansionChanged: ((newState) {
if (newState) {
setState(() {
_selected = i;
});
}
}),
children: [
Container(
height: 100,
padding: const EdgeInsets.all(10),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
LinearProgressIndicator(
minHeight: 5,
backgroundColor: Colors.black,
valueColor: AlwaysStoppedAnimation<Color>(Colors.green),
value: _selected == i ? _percent : 0,
),
Row(
children: [
(isPlay)? _Presso(
ico: Icons.pause,
onPressed: () {
setState(() {
isPlay=false;
});
advancedPlayer.pause();
}): _Presso(
ico: Icons.play_arrow,
onPressed: () {
setState(() {
isPlay=true;
});
advancedPlayer.play(widget.records.elementAt(i),
isLocal: true);
setState(() {});
setState(() {
_selected = i;
_percent = 0.0;
});
advancedPlayer.onPlayerCompletion.listen((_) {
setState(() {
_percent = 0.0;
});
});
advancedPlayer.onDurationChanged.listen((duration) {
setState(() {
_totalTime = duration.inMicroseconds;
});
});
advancedPlayer.onAudioPositionChanged
.listen((duration) {
setState(() {
_currentTime = duration.inMicroseconds;
_percent = _currentTime.toDouble() /
_totalTime.toDouble();
});
});
}),
_Presso(
ico: Icons.stop,
onPressed: () {
advancedPlayer.stop();
setState(() {
_percent = 0.0;
});
}),
_Presso(
ico: Icons.delete,
onPressed: () {
Directory appDirec =
Directory(widget.records.elementAt(i));
appDirec.delete(recursive: true);
Fluttertoast.showToast(msg: "File Deleted");
setState(() {
widget.records
.remove(widget.records.elementAt(i));
});
}),
_Presso(
ico: Icons.share,
onPressed: () {
Directory appDirec =
Directory(widget.records.elementAt(i));
List<String>list=List.empty(growable: true);
list.add(appDirec.path);
Share.shareFiles(list);
}),
],
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
),
],
),
),
],
),
);
},
);
}
String _getTime({required String filePath}) {
String fromPath = filePath.substring(
filePath.lastIndexOf('/') + 1, filePath.lastIndexOf('.'));
if (fromPath.startsWith("1", 0)) {
DateTime dateTime =
DateTime.fromMillisecondsSinceEpoch(int.parse(fromPath));
int year = dateTime.year;
int month = dateTime.month;
int day = dateTime.day;
int hour = dateTime.hour;
int min = dateTime.minute;
String dato = '$year-$month-$day--$hour:$min';
return dato;
} else {
return "No Date";
}
}
}
class _Presso extends StatelessWidget {
final IconData ico;
final VoidCallback onPressed;
const _Presso({Key? key, required this.ico,required this.onPressed}) : super(key: key);
@override
Widget build(BuildContext context) {
return ButtonTheme(
minWidth: 48.0,
child: RaisedButton(
child: Icon(
ico,
color: Colors.white,
),
onPressed: onPressed),
);
}
}
|
view.dart file
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'audio_recorder.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
class Recorder extends StatefulWidget {
final Function save;
const Recorder({Key? key, required this.save}) : super(key: key);
@override
_RecorderState createState() => _RecorderState();
}
class _RecorderState extends State<Recorder> {
IconData _recordIcon = Icons.mic_none;
MaterialColor colo = Colors.orange;
RecordingStatus _currentStatus = RecordingStatus.Unset;
bool stop = false;
Recording? _current;
// Recorder properties
late FlutterAudioRecorder? audioRecorder;
@override
void initState() {
super.initState();
checkPermission();
}
checkPermission()async{
if (await Permission.contacts.request().isGranted) {
// Either the permission was already granted before or the user just granted it.
}
// You can request multiple permissions at once.
Map<Permission, PermissionStatus> statuses = await [
Permission.microphone,
Permission.storage,
].request();
print(statuses[Permission.microphone]);
print(statuses[Permission.storage]);
//bool hasPermission = await FlutterAudioRecorder.hasPermissions ?? false;
if (statuses[Permission.microphone]==PermissionStatus.granted) {
_currentStatus = RecordingStatus.Initialized;
_recordIcon = Icons.mic;
}else
{
}
}
@override
void dispose() {
_currentStatus = RecordingStatus.Unset;
audioRecorder = null;
super.dispose();
}
@override
Widget build(BuildContext context) {
return Stack(
alignment: Alignment.center,
children: [
Column(
children: [
SizedBox(height: 20,),
Text(
(_current==null)?"0:0:0:0":_current!.duration.toString() ?? "0:0:0:0",
style: TextStyle(color: Colors.black, fontSize: 20),
),
SizedBox(height: 20,),
stop == false
? RaisedButton(
color: Colors.orange,
onPressed: () async {
await _onRecordButtonPressed();
setState(() {});
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: Column(
children: [
Container(
width: 80,
height: 80,
child: Icon(
_recordIcon,
color: Colors.white,
size: 80,
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Write Dailry",style: TextStyle(color: Colors.white),),
)
],
),
)
: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
RaisedButton(
color: colo,
onPressed: () async {
await _onRecordButtonPressed();
setState(() {});
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: Container(
width: 80,
height: 80,
child: Icon(
_recordIcon,
color: Colors.white,
size: 50,
),
),
),
RaisedButton(
color: Colors.orange,
onPressed: _currentStatus != RecordingStatus.Unset
? _stop
: null,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: Container(
width: 80,
height: 80,
child: Icon(
Icons.stop,
color: Colors.white,
size: 50,
),
),
),
],
),
),
],
),
],
);
}
Future<void> _onRecordButtonPressed() async {
switch (_currentStatus) {
case RecordingStatus.Initialized:
{
_recordo();
break;
}
case RecordingStatus.Recording:
{
_pause();
break;
}
case RecordingStatus.Paused:
{
_resume();
break;
}
case RecordingStatus.Stopped:
{
_recordo();
break;
}
default:
break;
}
}
_initial() async {
Directory? appDir = await getExternalStorageDirectory();
String jrecord = 'Audiorecords';
String dato = "${DateTime.now()!.millisecondsSinceEpoch?.toString()}.wav";
Directory appDirec =
Directory("${appDir!.path}/$jrecord/");
if (await appDirec.exists()) {
String patho = "${appDirec.path}$dato";
print("path for file11 ${patho}");
audioRecorder = FlutterAudioRecorder(patho, audioFormat: AudioFormat.WAV);
await audioRecorder!.initialized;
} else {
appDirec.create(recursive: true);
Fluttertoast.showToast(msg: "Start Recording , Press Start");
String patho = "${appDirec.path}$dato";
print("path for file22 ${patho}");
audioRecorder = FlutterAudioRecorder(patho, audioFormat: AudioFormat.WAV);
await audioRecorder!.initialized;
}
}
_start() async {
await audioRecorder!.start();
var recording = await audioRecorder!.current(channel: 0);
setState(() {
_current = recording!;
});
const tick = const Duration(milliseconds: 50);
new Timer.periodic(tick, (Timer t) async {
if (_currentStatus == RecordingStatus.Stopped) {
t.cancel();
}
var current = await audioRecorder!.current(channel: 0);
// print(current.status);
setState(() {
_current = current!;
_currentStatus = _current!.status!;
});
});
}
_resume() async {
await audioRecorder!.resume();
Fluttertoast.showToast(msg: "Resume Recording");
setState(() {
_recordIcon = Icons.pause;
colo = Colors.red;
});
}
_pause() async {
await audioRecorder!.pause();
Fluttertoast.showToast(msg: "Pause Recording");
setState(() {
_recordIcon = Icons.mic;
colo = Colors.green;
});
}
_stop() async {
var result = await audioRecorder!.stop();
Fluttertoast.showToast(msg: "Stop Recording , File Saved");
widget.save();
setState(() {
_current = result!;
_currentStatus = _current!.status!;
_current!.duration = null;
_recordIcon = Icons.mic;
stop = false;
});
}
Future<void> _recordo() async {
Map<Permission, PermissionStatus> statuses = await [
Permission.microphone,
Permission.storage,
].request();
print(statuses[Permission.microphone]);
print(statuses[Permission.storage]);
//bool hasPermission = await FlutterAudioRecorder.hasPermissions ?? false;
if (statuses[Permission.microphone]==PermissionStatus.granted) {
/* }
bool hasPermission = await FlutterAudioRecorder.hasPermissions ?? false;
if (hasPermission) {*/
await _initial();
await _start();
Fluttertoast.showToast(msg: "Start Recording");
setState(() {
_currentStatus = RecordingStatus.Recording;
_recordIcon = Icons.pause;
colo = Colors.red;
stop = true;
});
} else {
Fluttertoast.showToast(msg: "Allow App To Use Mic");
}
}
}
|
main.dart file
import 'package:flutter/material.dart';
import 'package:flutter_audio_record/home.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.pink,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: HomePage(
title: 'Recordings',
),
);
}
}
|
Conclusion: In this Audio recording application we cover how to record audio file in flutter and also learned share files from flutter application.
Article Contributed By :
|
|
|
|
14771 Views |