Flutter - How to save recorded audio file? - flutter

I am using flutter_sound to record voice(audio).
I can't see any file save on the emulator after the recording stops.
Recorder class:
import 'package:flutter/material.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:permission_handler/permission_handler.dart';
final _pathToAudio = 'myFile.aac';
class Recorder {
FlutterSoundRecorder? _recorder;
bool _isRecorderInitialized = false;
bool get isRecording => _recorder!.isRecording;
Future init() async {
_recorder = FlutterSoundRecorder();
final status = await Permission.microphone.request();
if (status != PermissionStatus.granted) {
throw RecordingPermissionException('Recording permission required.');
}
await _recorder!.openAudioSession();
_isRecorderInitialized = true;
}
void dispose() {
_recorder!.closeAudioSession();
_recorder = null;
_isRecorderInitialized = false;
}
Future record() async {
if (!_isRecorderInitialized) {
return;
}
print('recording....');
await _recorder!.startRecorder(
toFile: _pathToAudio,
codec: Codec.aacADTS,
);
}
Future stop() async {
if (!_isRecorderInitialized) {
return;
}
await _recorder!.stopRecorder();
print('stopped....'); //I GET THIS MESSAGE SO I AM GUESSING THE RECORDING IS HAPPENING BUT CANT FIND THE FILE LATER IN THE EMULATOR.
}
Future toggleRecording() async {
if (_recorder!.isStopped) {
await record();
} else {
await stop();
}
}
}
Function on button click:
void startStopRecording() async {
final isRecordingOn = await recorder.toggleRecording();
setState(() {
_isRecording = recorder.isRecording;
});
if(_isRecording) {
startTimer();
_stopwatch.start();
} else {
stopTimer();
_stopwatch.stop();
}
}

Related

Audio file not playing through platform channel

I'm trying to play an audio file on iOS with custom written platform channel. I have no errors when trying to play it, but I can't hear any sound from the phone/simulator.
When I try just_audio everything works great, so the problem is not about file path. You can test the commented method of playing it with just_audio. But when I try to play it through the platform channel, I can't hear any sound
This is my AppDelegate.swift:
import UIKit
import Flutter
import AVFoundation
#UIApplicationMain
#objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let playerChannel = FlutterMethodChannel(name: "PlayerChannel",
binaryMessenger: controller.binaryMessenger)
playerChannel.setMethodCallHandler({
[weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in
// This method is invoked on the UI thread.
guard call.method == "play" else {
result(FlutterMethodNotImplemented)
return
}
guard let args = call.arguments as? [String : Any] else {return}
let text = args["path"] as! String
self?.playAudio(result: result, path: text)
})
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
private func playAudio(result: FlutterResult, path: String) {
do{
let audioData = try Data.init(contentsOf:URL(fileURLWithPath: path))
try AVAudioSession.sharedInstance().setMode(.default)
try AVAudioSession.sharedInstance().setActive(true)
let audioPlayer = try AVAudioPlayer.init(data: audioData)
audioPlayer.play()
} catch {
print(String(describing: error))
result(FlutterError(code: "UNAVAILABLE",
message: "error.",
details: nil))
}
}
}
And this is how I call this method from my dart file:
import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:just_audio/just_audio.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
static const platform = MethodChannel('PlayerChannel');
Future<String> getPath() async {
Directory tempDir = await getTemporaryDirectory();
String tempPath = tempDir.path;
var filePath = "$tempPath/brown_noise.mp3";
var file = File(filePath);
if (file.existsSync()) {
return file.path;
} else {
final byteData = await rootBundle.load('assets/brown_noise.mp3');
final buffer = byteData.buffer;
await file.create(recursive: true);
file.writeAsBytes(
buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
return file.path;
}
}
#override
void initState() {
super.initState();
Future.delayed(const Duration(milliseconds: 800), () async {
try {
await platform.invokeMethod('play', {'path': await getPath()});
} on PlatformException catch (e) {
log("Failed to play: '${e.message}'.");
}
/* final a = AudioPlayer();
a.setFilePath(await getPath());
a.play(); */
});
}
#override
Widget build(BuildContext context) {
return const Placeholder();
}
}

reset method send nothing

I have created a reset password method but the reset email didn’t arrive to the user mail
this is the method
void forgotPass()async {
if(_emailController.text.isEmpty || !_emailController.text.contains('#')){
Methods.ErrorDailog(subtitle: "Pleas enter a valid email", context: context);
}else{
setState(() {
isLoading= true;
});
try {
await authInstance.sendPasswordResetEmail(email: _emailController.text.toLowerCase());
} on FirebaseAuthException catch (error) {
Methods.ErrorDailog(subtitle: '${error.message}', context: context);
setState(() {
isLoading = true;
});
} catch (error) {
Methods.ErrorDailog(subtitle: '$error', context: context);
setState(() {
isLoading = true;
});
} finally {
setState(() {
isLoading = false;
});
}
}
}

Able to access current location locally but not on flutter web and deployment with exception (MissingPluginException....)

MissingPluginException(No implementation found for method placemarkFromCoordinates on channel flutter.baseflow.com/geocoding)
I want to access the current location of device and I am able to get it locally, but on flutter web and after deployment it gives me the exception above, how to handle this exception please.
Future<Position> _getCurrentLocation() async {
bool serviceEnabled;
LocationPermission permission;
serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
return Future.error('Location services are disabled.');
}
permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) {
return Future.error('Location permissions are denied');
}
}
if (permission == LocationPermission.deniedForever) {
// Permissions are denied forever, handle appropriately.
return Future.error(
'Location permissions are permanently denied, we cannot request permissions.');
}
Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.best,
forceAndroidLocationManager: true)
.then((Position position) {
setState(() {
_currentPosition = position;
_getAddressFromLatLng();
});
}).catchError((e) {
if (kDebugMode) {
print(e);
}
});
return await Geolocator.getCurrentPosition();
}
Here I am converting the LAT LNG to Address.
_getAddressFromLatLng() async {
try {
List<Placemark> placemarks = await placemarkFromCoordinates(
_currentPosition!.latitude, _currentPosition!.longitude);
Placemark place = placemarks[0];
setState(() {
_currentAddress = "${place.locality}, ${place.country}";
});
} catch (e) {
if (kDebugMode) {
print(e);
}
}
}

async task is not Working in WorkManagers CallbackDispatcher

I am using WorkManager for Background Service. My code is as follows
void callbackDispatcher() {
Workmanager.executeTask((task, inputData) async {
switch (task) {
case "uploadLocalData":
print("this method was called from background!");
await BackgroundProcessHandler().uploadLocalData();
print("background Executed!");
return true;
break;
case Workmanager.iOSBackgroundTask:
print("iOS background fetch delegate ran");
return true;
break;
}
return false;
});
}
is there any way to wait for async method in executeTask ?
The way to asyncify non-async things is through completers. You create a completer, await on its future and complete it in the future.
Completer uploadCompleter = Completer();
void callbackDispatcher() {
Workmanager.executeTask((task, inputData) async {
switch (task) {
case "uploadLocalData":
print("this method was called from background!");
await BackgroundProcessHandler().uploadLocalData();
print("background Executed!");
uploadCompleter.complete();
return true;
break;
case Workmanager.iOSBackgroundTask:
print("iOS background fetch delegate ran");
return true;
break;
}
return false;
});
}
// somewhere else
await uploadCompleter.future;

unable to get user location when the app starts in flutter

I want to get user location when the app starts.
This code runs fine when I already have the location enabled before starting the app and then I start the the app. But when it is disabled and then start the app, I am unable to get the location.
Below is what the snippet looks like:
Future<void> _isLocationEnabled() async {
_serviceEnabled = await location.serviceEnabled();
if (!_serviceEnabled) {
_serviceEnabled = await location.requestService();
if (!_serviceEnabled) {
setState(() {
_isLoading = false;
});
showModalBottomSheet(
//showing modal sheet here
});
} else {
try {
locationData = await Location().getLocation();
} catch (e) {
print(e);
}
setState(() {
_isLoading = false;
});
}
} else {
locationData = await Location().getLocation();
setState(() {
_isLoading = false;
});
}
_permissionGranted = await location.hasPermission();
if (_permissionGranted == PermissionStatus.denied) {
_permissionGranted = await location.requestPermission();
if (_permissionGranted != PermissionStatus.granted) {
return;
}
}
}
The thing is that the catch block doesnt run nor I am able to get the location.
I call this function in initState like this:
#override
void initState() {
super.initState();
_isLocationEnabled();
}
Is there something I am missing?
I had a similar issue, try to get the location after a delay.
The below code should do the trick
Future<void> _isLocationEnabled() async {
_serviceEnabled = await location.serviceEnabled();
if (!_serviceEnabled) {
_serviceEnabled = await location.requestService();
if (!_serviceEnabled) {
setState(() {
_isLoading = false;
});
showModalBottomSheet(
//showing modal sheet here
);
} else {
try {
Future.delayed(Duration(seconds: 1), () async {
locationData = await Location().getLocation();
print(locationData);
});
} catch (e) {
print(e);
}
setState(() {
_isLoading = false;
});
}
} else {
locationData = await Location().getLocation();
setState(() {
_isLoading = false;
});
}
_permissionGranted = await location.hasPermission();
if (_permissionGranted == PermissionStatus.denied) {
_permissionGranted = await location.requestPermission();
if (_permissionGranted != PermissionStatus.granted) {
return;
}
}
}