Closed: How to read a temporary file as bytes in Flutter? - flutter

So basically I am using flutter_sound to record an audio file:
class AudioRecorder {
FlutterSoundRecorder? _audioRecorder;
String tempFilePath = "audio_recording.mp4";
Future<void> init() async {
_audioRecorder = FlutterSoundRecorder();
await _audioRecorder!.openRecorder();
}
Future<void> dispose() async {
await _audioRecorder!.openRecorder();
_audioRecorder = null;
}
Future<void> startRecording() async {
await _audioRecorder!.startRecorder(toFile: tempFilePath);
}
Future<File> stopRecording() async {
await _audioRecorder!.stopRecorder();
return File(tempFilePath);
}
}
This class works as intended and a file is returned by stopRecording();.
The issue:
When I try to audioFile.readAsBytesSync();, this error occurs:
Unhandled Exception: FileSystemException: Cannot open file, path = 'audio_recording.mp4' (OS Error: No such file or directory, errno = 2)
What I think is wrong:
When I do print(audioFile.path);, the output is "audio_recording.mp4" however when I stop recording the audio, flutter_sound also prints a path to the file but its different:
"/Users/.../Library/Developer/CoreSimulator/Devices/.../data/Containers/Data/Application/.../tmp/audio_recording.mp4"
When I readAsBytesSync to a File object that has this path, there is no exception. So I somehow have to get this path but I cannot figure out how. I have tried using path_provider and getTemporaryDirectory but its to no avail since the path from getTemporaryDirectory is different to the one printed by flutter_sound.
How could I fix this?
Thank you!

Related

Not able to upload file to firebase storage in Flutter

i'm trying to do the upload of image files to the cloud firestore in firebase using flutter. i'm always getting the following error and I do not understand where the issue is.
FirebaseException ([firebase_storage/object-not-found] No object exists at the desired reference.)
console:
E/StorageException(10183): StorageException has occurred.
E/StorageException(10183): Object does not exist at location.
E/StorageException(10183): Code: -13010 HttpResult: 404
Here is my code:
class DatabaseMethods {
CollectionReference cartesPro =
FirebaseFirestore.instance.collection('cartesPro');
FirebaseStorage storage = FirebaseStorage.instance;
Future<String> uploadFile(file) async {
Reference reference = storage.ref().child('cartesPro/');
print('REFERENCE: ${reference}');
UploadTask uploadTask = reference.putFile(file);
print('UPLOAD TASK${uploadTask.snapshot}');
TaskSnapshot taskSnapshot = await uploadTask;
return await taskSnapshot.ref.getDownloadURL();
}
void addFile(CartPro cartPro) {
cartesPro.add({
"cartUserId": cartPro.cartUserId,
"cartTimestamp": FieldValue.serverTimestamp()
});
}
}
Log of reference and uploadTask snapshot:
I/flutter (10183): REFERENCE: Reference(app: [DEFAULT], fullPath: cartesPro)
I/flutter (10183): UPLOAD TASK: TaskSnapshot(ref: Reference(app: [DEFAULT], fullPath: cartesPro), state: TaskState.running)
Everything seems pretty fine to me but still I do always get that error!
I'd be grateful for any kind of help!
First, make sure your firebase storage rules are correct.
Example:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write;
}
}
}
Second, try pushing the data that comes as File as Uint8List.
Example:
Future<String> uploadFile(File file, String uid) async {
Reference reference = storage.ref().child('cartesPro/').child(uid); //It's helpful to name your file uniquely
Uint8List bytes = file.readAsBytesSync(); //THIS LINE
var snapshot = await reference.putData(bytes); //THIS LINE
return await snapshot.ref.getDownloadURL();
}

Unhandled Exception: PlatformException(channel-error, Unable to establish connection on channel

Unhandled Exception: PlatformException(channel-error, Unable to establish connection on channel
Please don't let me upgrade my firebase.... My app don't have it at all..
Here was my code for get this trouble:
LazyDatabase _openConnection() {
// the LazyDatabase util lets us find the right location for the file async.
return LazyDatabase(() async {
// put the database file, called db.sqlite here, into the documents folder
// for your app.
// final dbFolder = await getApplicationDocumentsDirectory();
final dbFolder = await getApplicationDocumentsDirectory();
final file = File(p.join(dbFolder.path, 'chat.sqlite'));
if (!await file.exists()) {
print('!!!!!!!!!!!!! sql not exist! create it.');
}
return NativeDatabase(file);
});
}
it ca nnot acccesss to docment directory seems

Flutter recording feature working on emulator but not on actual device

I am developing an app that can record and play sound. Everything works fine on my emulator. But when I try to run the app on my device, it always gives me this error:
java.lang.NullPointerException: Attempt to invoke virtual method 'long android.os.storage.StorageVolume.getMaxFileSize()' on a null object reference
The way I implement the recording feature is to record the audio to a temporary file, and playback from it. This is the corresponding code, I am using flutter sound by the way:
String pathToSaveAudio = '';
class SoundRecorder {
FlutterSoundRecorder? _audioRecorder;
bool _isRecordingInitialised = false;
bool get isRecording => _audioRecorder!.isRecording;
// getters
bool getInitState() {
return _isRecordingInitialised;
}
FlutterSoundRecorder? getRecorder() {
return _audioRecorder;
}
/// init recorder
Future init() async {
_audioRecorder = FlutterSoundRecorder();
final status = await Permission.microphone.request();
if (status != PermissionStatus.granted) {
throw RecordingPermissionException('Microphone permission denied');
}
await _audioRecorder!.openRecorder();
_isRecordingInitialised = true;
var tempDir = await getTemporaryDirectory();
pathToSaveAudio = '${tempDir.path}/audio.mp4';
}
/// dipose recorder
void dispose() {
_audioRecorder!.closeRecorder();
_audioRecorder = null;
_isRecordingInitialised = false;
}
/// start record
Future _record() async {
assert(_isRecordingInitialised);
await _audioRecorder!
.startRecorder(toFile: pathToSaveAudio, codec: Codec.aacMP4);
}
/// stop record
Future _stop() async {
if (!_isRecordingInitialised) return;
await _audioRecorder!.stopRecorder();
}
I think what I'm doing is record the sound and put it in the file in that temp directory. But appearently the app want to acces the file before I even start recording. At this point, I don't know what to do, please help me.

flutter opening a Hive box gives error -says box not found, Did you forget to call Hive openbox()

I have a class where I am doing the graphql setup and the hive box setup. Here is the class -
class GraphQLConfiguration {
ValueNotifier<GraphQLClient> client = new ValueNotifier<GraphQLClient>(
GraphQLClient(
cache:
GraphQLCache(store: HiveStore(Hive.box(HiveStore.defaultBoxName))),
link: HttpLink('http://localhost:4000/graphql/',),
),
);
GraphQLConfiguration() {
initializeHive();
}
void initializeHive() async {
await initHiveForFlutter(); // or await initHiveForFlutter();
await Hive.openBox('bolBox');
}
}
Now I initialize this class in the Flutter main method -
Future main() async {
GraphQLConfiguration graphql = new GraphQLConfiguration();
}
When I run this code I get this error message -
Error - Unhandled Exception: HiveError: Box not found. Did you forget to call Hive.openBox()?
I followed this post as well Box not found. Did you forget to call Hive.openBox()?, didn't help.
Initialize Hive by giving it a home directory by using path_provider
final Directory appDocDir = await getApplicationDocumentsDirectory();
Hive.init(appDocDir.path);
then open box
await Hive.openBox('bolBox');
Add initHiveForFlutter in your root folder & it solve the problem.
void main() async{
await initHiveForFlutter();
runApp(MyApp());
}
Worked for me.
No need to initialise with open box & path as GraphQl handles that internally inside initHiveForFlutter.

How to get the absolute path of a file in flutter

I am working on a Flutter project to syntehsise an string to an audio file. For this reason, I have added flutter_tts as a dependency and implemented the following method with different approaches in order to check the existence of the generated file:
/// Synthesises the current audio cue into an audio file
static Future<void> synthesiseStringToAudioFile() async {
Future<String> finalPath;
Future<File> finalFile;
Uri uriToFile;
String absolutePath;
bool existsPath;
bool existsManually;
bool exists3;
await flutterTts
.synthesizeToFile("This is my first audio synthesizer in Flutter",
audioFileName)
.then((value) => {
// File has been successfully created
if (value == 1)
{
// Gets the path to the generated audio file
finalPath = pathToFile,
finalPath.then((path) async => {
print('AFile :Path to audio file: $path'),
// Check if exists
existsPath = FileSystemEntity.typeSync(path) != FileSystemEntityType.notFound,
print("AFile : Exists? $existsPath"),
existsManually = await File('/storage/emulated/0/Android/data/mypath/files/temp_audio_cue.wav').exists(), // Requieres async function
print("AFile : Exists2? $existsManually"), // RETURNS TRUE
exists3 = await File(path).exists(),
print("AFile : Exists3? $exists3")
}),
// Gets the generated file
finalFile = localFile,
finalFile.then((file) => {
// Absolute path
absolutePath = file.absolute.path,
print('AFile : AbsolutePath: $absolutePath'),
// Check the URI
uriToFile = file.uri,
print('AFile : URI to audio file: $uriToFile'),
}),
}
else
{print('There was an error during the synthezisation')}
});
}
static void setAudioFileName() {
audioFileName = Platform.isAndroid ? "temp_audio_cue.wav" : "temp_audio_cue.caf";
}
/// Gets the path to the file to be accessed
static Future<String> get pathToFile async {
final path = await localPath;
return '$path/$audioFileName';
}
/// Gets the path to the local directory
static Future<String> get localPath async {
final dir = await getApplicationDocumentsDirectory();
return dir.path;
}
Once the synthesisation is completed, flutterTts.synthesizeToFile() logs in console the following message:
D/TTS (10335): Successfully created file :
/storage/emulated/0/Android/data/mypath/files/temp_audio_cue.wav
so if I check the existence of the file manually (as I do with existManually) will get a true value, but I am not able to do it trying to get dynamically the path as in the other examples I am trying but the ones I am getting are:
/data/user/0/mypath/app_flutter/temp_audio_cue.wav
so it is missing the beginning
/storage/emulated/0/Android/
I was wondering what is the correct way to get the path to the file (missing)?
With path_provider in Android save in getExternalStorageDirectory and in iOS save in getApplicationDocumentsDirectory..
If you want to get this path : /storage/emulated/0
Use path_provider_ex package, which provides root and app files directory for both "external storage" (internal flash) and SD card (if present), as well as available space for each storage.
you can use path_provider package of flutter
Directory appDocDir = await getApplicationDocumentsDirectory();
String appDocPath = appDocDir.path;
https://pub.dev/packages/path_provider
I am using filesystem_picker to return absolute paths from storage and then using File('path_string') or Directory('path_string') to get the actual file.
Using manageExternalStorage permissions allows this work, but keep in mind:
"The Google Play store has a policy that limits usage of MANAGE_EXTERNAL_STORAGE".
This also may not work depending on the SDK you are using and/or conflicts from other packages.
import 'package:filesystem_picker/filesystem_picker.dart';
import 'package:permission_handler/permission_handler.dart';
Directory? rootDir;
late String tempDir;
_getFile(){
await _pickFile();
String path = tempDir;
var file = File(path);
// Do stuff with file
}
// Call this before _pickFile(), ideally inside initState()
Future<void> _prepareStorage() async {
rootDir = Directory('/storage/emulated/0/');
var storageExternal = await Permission.manageExternalStorage.status;
if (storageExternal != PermissionStatus.granted) {
await Permission.manageExternalStorage.request();
}
bool b = storageExternal == PermissionStatus.granted;
//mPrint("STORAGE ACCESS IS : $b");
}
Future<void> _pickFile(BuildContext context) async {
await FilesystemPicker.open(
title: 'Select file',
context: context,
rootDirectory: rootDir!,
fsType: FilesystemType.file,
pickText: 'Select file to add',
folderIconColor: Colors.teal,
requestPermission: () async => await Permission.manageExternalStorage.request().isGranted,
).then((value){
if (value != null){
tempDir = value.toString();
}
else{
tempDir = "";
}
//mPrint(tempDir);
});
}
Add the following to AndroidManifest.xml:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" android:minSdkVersion="30" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:label="test_flutter"
android:name="${applicationName}"
android:icon="#mipmap/ic_launcher"
android:requestLegacyExternalStorage="true"
>
I tried and it worked
import 'package:path_provider/path_provider.dart';
Future<File> getImageFileFromAssets(Asset asset) async {
final byteData = await asset.getByteData();
final tempFile =
File("${(await getTemporaryDirectory()).path}/${asset.name}");
final file = await tempFile.writeAsBytes(
byteData.buffer
.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes),
);
return file;
}